SE

Language runtime basics

Must-know concept2.5 hIntermediate

Memory, stack vs heap, garbage collection, async I/O, threads, and processes.

Frameworks hide the runtime until something gets slow, stuck, or memory-hungry. Knowing how code actually runs helps you debug performance and choose safer architecture.

The big idea

Your code runs inside a runtime that manages memory, schedules work, talks to the OS, and decides how concurrency happens.

L4

handlers, services, jobs

L3

VM, GC, event loop, thread pool

L2

memory, files, sockets, signals

L1

CPU scheduling, network, disk

When production is slow, the bug may be in any of those layers.

Stack and heap

Stack
Function calls and short-lived local state. Fast, structured, limited.
Heap
Objects that outlive one call frame. Flexible, garbage-collected or manually managed.
Pointer/reference
A small value that points at data somewhere else.
Garbage collection
Runtime cleanup of unreachable heap objects.

Memory leaks in garbage-collected languages still happen: a cache, global list, closure, or listener can keep references alive forever.

Processes, threads, and async

AttributeWhat it isTrade-off
ProcessOwn memory spaceStrong isolation, heavier startup
ThreadShares process memoryCheap sharing, synchronization risk
Coroutine/taskRuntime-scheduled workGreat for I/O, not magic CPU parallelism
Event loopOne loop dispatches callbacksBlocked by long CPU work

Async code helps when waiting on network, disk, or timers. It does not make CPU-heavy code free. A single blocking loop can freeze an event-loop service.

Common runtime failures

High CPU
Hot loop, expensive serialization, compression, crypto, or too much concurrency.
High memory
Unbounded cache, large response, leaked listeners, or data loaded all at once.
Stuck requests
Thread pool exhaustion, blocked event loop, missing timeout, or deadlock.
Slow startup
Heavy imports, migrations at boot, cold caches, or synchronous network calls.

What to inspect

top
ps -o pid,ppid,%cpu,%mem,cmd -p <pid>
lsof -p <pid>
curl -w '%{time_total}\n' -o /dev/null -s http://localhost:3000/

In language-specific tools, learn the profiler, heap snapshot, thread dump, or event-loop delay monitor for the runtime you use most.

Runtime-specific instincts

  • Node.js: avoid long CPU work on the event loop; watch event-loop delay.
  • Python: understand the GIL; use async for I/O and workers/processes for CPU.
  • Java/JVM: watch heap size, GC pauses, thread pools, and warmup.
  • Go: goroutines are cheap, but leaks and unbounded channels still hurt.

In practice

Write a tiny endpoint that sleeps, another that loops CPU for two seconds, and another that allocates a large array. Hit each with concurrent requests. Watch how the runtime behaves. This is more memorable than a page of definitions.

Key takeaways

  • The runtime schedules work, manages memory, and turns code into OS activity.
  • Garbage collection prevents many manual frees, but not leaked references.
  • Async helps I/O waits; CPU-heavy code still needs separate capacity.
  • Threads, processes, event loops, and coroutines fail in different ways.
  • Learn one profiler or runtime inspection tool before you need it in an outage.

Checkpoint questions

Use these to test whether the lesson is clear enough to explain without rereading.

  1. 1What lives on the stack, what lives on the heap, and why does that matter?
  2. 2How do threads, processes, coroutines, and event loops differ?
  3. 3What can block an async service even when the code uses async syntax?
  4. 4Which runtime behavior would you inspect for high memory, high CPU, or stuck requests?

References

External resources for going deeper after the lesson above.