{
  "id": 6715773,
  "title": "Optimizing a Spin-Lock",
  "url": "https://urgent.news/2026/09/10/optimizing-a-spin-lock",
  "topic": "tech",
  "section": "Tech",
  "published": "2026-09-10T20:34:57.000Z",
  "source": {
    "name": "Lobsters",
    "slug": "lobsters",
    "url": "https://david.alvarezrosa.com/posts/optimizing-a-spin-lock/"
  },
  "original_language": "en",
  "account": "A spin-lock is a lock that continuously loops instead of relinquishing control. This post constructs a faster and more energy-efficient version, illustrating a 5.7x performance boost and 5.4x reduction in energy consumption. The lock increments a shared counter while threads access it. The lock and counter each occupy a cache line. Threads are assigned to specific cores. An atomic boolean and exchange loop facilitate the lock. An atomic exchange operation sets a flag to true, signaling lock acquisition. False indicates the lock is available, allowing the thread to proceed. True indicates the lock is held by another thread, prompting the thread to retry. The exchange takes 3.14 nanoseconds for a single thread, multiplying to 61.5 nanoseconds for twenty threads. Four threads experience 246 nanoseconds. L1-d misses increase from 1.27% to 61.73%, with one branch misprediction every eight attempts. The exchange's success depends on other cores, leaving the branch predictor without relevant information. Spinning incurs energy costs, impacting high-frequency trading operations that pay for power. At four threads, the system consumes 64.92 joules. The RAPL counters, measured system-wide, capture the total energy usage, including idle cores. The default memory ordering, seq_cst, is stronger than necessary for this lock. The lock requires only an acquire on entry and a release on exit. This adjustment reduces the unlocked time to 1.57 nanoseconds uncontended, and 131 nanoseconds for four threads. L1-d misses decrease from 61.73% to 21.16%, with branch mispredictions falling from 12.52% to 7.43%. Energy consumption drops to 34.45 joules. The exchange operation writes to the shared line, even if it fails. Waiters must cease writing and wait on a read-only load. The _mm_pause instruction signals the loop as a spin-wait, allowing the core to idle. Waiters can relax the load operation. The exchange informs the critical section, while the failed reads have no ordering impact. Two threads experience a 32.5 nanosecond reduction, dropping to 21.3 nanoseconds. Four threads achieve an 8% improvement, from 131 nanoseconds to 120 nanoseconds. L1-d misses fall from 21.16% to 17.31%, with branch mispredictions decreasing to 3.72%. A read-only spin is more predictable, as all waiters pause simultaneously. Intel provides a fix for this scenario. Increasing back-off between retries can further improve performance, as seen in example 2-10 of the Intel Optimization Reference Manual. Two threads drop from 120 nanoseconds to 43.0 nanoseconds, and energy consumption falls to 11.92 joules, a 5.4x improvement over the initial version. In typical code, std::mutex remains the preferred choice. However, consider a spin-lock when threads are pinned to dedicated cores and after thorough benchmarking. For scenarios with many readers and one writer, a seqlock may be more suitable. For inquiries, email david@alvarezrosa.com.",
  "summary": null,
  "key_points": [],
  "editors_take": null,
  "illustration": null,
  "coverage": {
    "outlets": 1,
    "also_reported_by": []
  },
  "ai_generated": true,
  "disclaimer": "Summaries, key points and the editor’s take are written by software from other outlets’ reporting and may contain errors — always check the linked original."
}