Open this lesson in your favourite AI. It'll walk you through the why, explain the demo, and quiz you on the try-it list.
Choosing the wrong abstraction for a unit of concurrent work is a performance cliff that's hard to see coming. Processes start in milliseconds and cost megabytes each — they're isolated but expensive. OS threads share a heap and start in microseconds, but spawning thousands exhausts memory and the OS scheduler. Virtual threads, goroutines, and async tasks are managed by a user-space runtime, start in nanoseconds, and millions fit in a single process. The wrong choice materializes as a server that works fine at 100 req/s and falls over at 1,000 — or as a crash that takes down the whole process because a plugin thread corrupted shared memory.
Process: its own address space, its own file descriptors, its own heap. Start cost measured in milliseconds. Crashing one doesn't crash the others. Data has to be serialized to cross the boundary.
Thread: shares address space and heap with other threads in the same process. Start cost measured in microseconds. Crashing one can crash the process. Shared memory is fast — and a minefield.
Task / fiber / virtual thread: managed by a user-space runtime, not the OS. Start cost measured in nanoseconds. Millions of them can exist in a single process. The runtime decides when they pause and resume.
ulimit -s on Linux). Calculate the RAM used by 10,000 threads at that stack size.Use these three in order. Each builds on the one before.
Define 'process', 'OS thread', and 'virtual thread / task'. Give the typical memory footprint and startup cost of each.
Explain what gets duplicated on `fork()` vs. what gets shared when a new thread is created. Why does this make processes safer but slower?
Pick the right abstraction for: (a) isolating a plug-in that might segfault, (b) handling 100k WebSocket connections, (c) running a CPU-bound video transcode. Defend each choice.