liveBook · Manning

Memory allocation

As explained in Latency

Dynamic memory allocation is reserving and releasing storage during program execution from a runtime-managed memory region.

Dynamic memory allocation reserves and releases storage during execution in a region called the heap. It is a common source of work in latency-sensitive code, including work that changes unexpectedly with the application workload. section 7.4.1 section 7.4

A dynamic allocator obtains memory from the operating system for the process, then assigns smaller blocks to individual requests. In a simplified allocator, a linked list tracks free blocks. An allocation searches for a block large enough to use, possibly splitting it; releasing a block makes it available for a later request. Real allocators add layers and optimizations, but allocation still entails work rather than a fixed, deterministic cost. section 7.4.1

Figure 7.3 The dynamic memory allocator manages a section of memory we call the heap. In this example, the dynamic memory allocator maintains a list of free blocks in memory (freelist), which is a linked list of all the available blocks.
Figure 7.2: The dynamic memory allocator manages a section of the memory we call the heap. In this example, the dynamic memory allocator maintains a list of free blocks in the memory (freelist), which is a linked list of all the available blocks.

The free-list diagram makes the search, reuse, and possible splitting of heap blocks concrete. section 7.4.1

The way to request dynamic storage depends on the language: examples include `new`, C’s `malloc()`, and Rust’s `Box`. How much control a programmer has over lower-level allocation behavior also depends on the language and runtime; not every latency optimization available in a systems language transfers to a garbage-collected language. section 7.4.1 section 2.3

Measure before removing allocations

A Fibonacci benchmark compares a recursive implementation, a memoized version with a vector cache, and an iterative version. Reported times are about 157 ns, 44 ns, and 5 ns respectively. The gains have more than one cause: memoization changes the algorithmic complexity, while iteration also removes the dynamic allocation used by the cache. Benchmark the performance-sensitive path before attributing an improvement to allocation alone. section 7.7

How Latency covers it

How deep it goes
Explains heap requests, free-list search, splitting, and reuse through a simplified allocator, while noting that real allocators have additional layers.
Examples
Uses a Rust `Box` allocation, a free-list diagram, and measured recursive, memoized, and iterative Fibonacci implementations.
What it assumes
Assumes familiarity with programming examples but defines heap allocation and introduces the allocator’s basic free-list model.
What you can do after
Diagnose/debug with it by benchmarking latency-sensitive code and checking whether eliminating dynamic allocation removes useful work.
How it connects
Connects heap allocation to latency, garbage collection, memoization, iteration, and benchmarking.

Also explained in

Compare how 11 books explain memory allocation →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Latency. The section links point to the parts of the book it draws on.