Memory Locking and Cache Control
Page faults and cache misses cause unpredictable delays; locking memory and controlling cache behavior are standard techniques for real-time determinism.
Memory as a Source of Jitter
On systems with virtual memory and caches, memory access time is not constant. A page that has been swapped out triggers a slow disk access; a cache miss costs far more than a hit. These mechanisms improve average performance but introduce large, unpredictable delays that undermine determinism. Controlling memory behavior is therefore a routine part of real-time engineering.
Locking Memory
Real-time programs lock their critical pages into physical memory so the operating system cannot swap them out. Locking prevents page faults on the critical path, where a fault could add milliseconds to a loop that must finish in microseconds. Programs also pre-fault their memory at startup, touching every page so the mapping is established before real-time operation begins, and use static or pre-allocated memory to avoid allocation during the loop.
- Lock critical pages resident to prevent swapping and page faults
- Pre-fault memory at startup so no first-touch fault occurs later
- Avoid dynamic allocation on the critical path; pre-allocate pools
- Touch and warm data structures before the timed section runs
Cache Control
Caches speed the average case but a miss is costly and hard to predict. Techniques to tame this include locking critical code and data into cache so it cannot be evicted, partitioning the cache so a low-priority task cannot evict a high-priority task's working set, and using dedicated scratchpad memory whose access time is fixed. On multicore systems, isolating a critical task to a core reduces contention for shared cache levels.
The Underlying Principle
Each of these techniques trades some average performance for a tighter worst case. Locked memory cannot be reclaimed for other uses; a partitioned cache gives each task less room. Real-time engineering accepts these costs because the metric that matters is the maximum, not the mean. By removing the sources of large memory-related delays, the code's worst-case execution time becomes both smaller and, more importantly, provable, which is what the timing analysis requires.