💻 Operating Systems - Processes, Threads, & Memory
The Senior Mindset: Every line of code eventually competes for three things: CPU cycles, RAM, and IO bandwidth. A senior engineer understands how the OS schedules these resources to avoid bottlenecks like thread starvation, memory leaks, and IO blocking.
🧵 Processes vs. Threads
Section titled “🧵 Processes vs. Threads”The fundamental units of execution.
- Process: An independent program in execution with its own isolated memory space (Stack, Heap, Data). Processes do not share memory by default; they use IPC (Inter-Process Communication).
- Thread: A lightweight unit within a process. Multiple threads share the same memory space (Heap) but have their own Stacks.
- Risk: Shared memory leads to Race Conditions. You must use synchronization primitives like Mutexes or Semaphores.
🧠 Memory Management
Section titled “🧠 Memory Management”How the OS provides a sandbox for your application.
- Virtual Memory: The OS gives each process the illusion of having a vast, contiguous block of memory, mapping “Virtual Addresses” to physical RAM or disk (Swap).
- Stack vs. Heap:
- Stack: Fast, automatic allocation/deallocation. Used for local variables and function calls.
- Heap: Larger, manual (or Garbage Collected) allocation. Used for dynamic data that outlives a function call.
- Thrashing: Occurs when the system spends more time swapping data between RAM and Disk than executing code. This usually happens when the “Working Set” of your app exceeds available RAM.
📥 I/O Models: Blocking vs. Non-Blocking
Section titled “📥 I/O Models: Blocking vs. Non-Blocking”IO is usually the slowest part of any system. How the OS handles it determines your application’s throughput.
- Blocking IO: The thread waits (sleeps) until the data is ready. Simple to write, but scales poorly (one thread per connection).
- Non-Blocking / Event-Driven: The thread asks for data and moves on. The OS notifies the app when data is ready (e.g.,
epollin Linux).- Real-world Example: This is the heart of Node.js and Go’s high concurrency.
⚖️ Concurrency Challenges (The Senior Perspective)
Section titled “⚖️ Concurrency Challenges (The Senior Perspective)”Context Switching
Section titled “Context Switching”The OS must save the state of a CPU core to swap one thread for another.
- The Cost: Context switching is expensive. If you have 10,000 threads on a 4-core CPU, the system will spend all its time switching and no time working.
- Senior Solution: Use Thread Pools to limit the number of active threads or use Green Threads/Goroutines which are managed by the language runtime instead of the OS.
User Space vs. Kernel Space
Section titled “User Space vs. Kernel Space”- Kernel Space: Where the OS core runs. It has full hardware access.
- User Space: Where your app runs.
- The “System Call” Tax: Every time you read a file or send a network packet, your app must transition from User to Kernel space. Minimizing unnecessary system calls is a key performance optimization.
🛠️ Essential OS Concepts for Seniors
Section titled “🛠️ Essential OS Concepts for Seniors”| Concept | What it is | Why it matters |
|---|---|---|
| Scheduler | The part of the OS that decides which thread runs next. | Understanding “Preemption” helps you debug why a task is being delayed. |
| File Descriptors | Integers representing open files/sockets. | ”Too many open files” is a common production error when WebSockets or DB connections aren’t closed. |
| Deadlock | Two threads waiting for each other’s locks. | Requires a “Detection and Recovery” or “Prevention” strategy. |
💡 Seniority Note: Don’t blame the Garbage Collector (GC) immediately for performance issues. Often, the problem is Memory Pressure—your code is creating objects faster than the OS/Runtime can clean them up, forcing the GC to stop the world frequently.
🔗 Related Links
Section titled “🔗 Related Links”- [[Protocols-TCP-UDP]]
- [[Backend-Linguagens-Performance]]
- [[DevOps-Docker-Containers]]