Skip to content

perf: avoid hot-path atomic write when circuit state is unchanged#30

Open
costela wants to merge 1 commit into
mainfrom
perf/avoid-hotpath-atomic-write
Open

perf: avoid hot-path atomic write when circuit state is unchanged#30
costela wants to merge 1 commit into
mainfrom
perf/avoid-hotpath-atomic-write

Conversation

@costela

@costela costela commented Jun 26, 2026

Copy link
Copy Markdown
Member

What

Guard the openedAt mutation in stateObserver.Observe with a Load so a steady-state circuit doesn't write to shared state on every call.

Why

SlidingWindowBreaker.observe returns stateChangeClose on every below-threshold call, so a healthy closed circuit ran openedAt.Store(0) on every call — an unconditional atomic write to a cache line that's already 0. Under concurrency that bounces the line between cores (MESI invalidation), reintroducing exactly the cross-core contention the lock-free design exists to avoid — for a write that changes nothing.

How

  • stateChangeOpen → only open() if openedAt.Load() == 0.
  • stateChangeClose → only close() if openedAt.Load() != 0.

A Load keeps the cache line shared across cores; the steady-state happy path becomes read-only.

Results (benchstat, parallel)

Benchmark Δ
EWMA-8 −42.7%
EWMA-16 −35.6%
SlidingWindow-16 −31.0%
SlidingWindow (1 core) ~ (no contention to relieve)

Gains scale with core count, as the contention hypothesis predicts.

🤖 Generated with Claude Code

SlidingWindowBreaker.observe returns stateChangeClose on every call below
threshold, so a healthy closed circuit executed openedAt.Store(0) on every
single call - an unconditional atomic write to one shared cache line that is
already 0. Under concurrency this bounces the cache line between cores (MESI
invalidation), reintroducing the cross-core contention the lock-free design
exists to avoid, for a write that changes nothing.

Guard both transitions with a Load first: only open() when currently closed
and only close() when currently open. A Load keeps the cache line shared
across cores; the steady-state happy path becomes read-only. open()'s
CompareAndSwap already no-ops when already open, but the Load avoids even
issuing the read-modify-write.

Benchstat (parallel benchmarks): ~9-43% faster, scaling with core count
exactly as the contention hypothesis predicts; single-threaded SlidingWindow
shows no change (no contention to relieve).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@costela costela marked this pull request as ready for review June 26, 2026 19:06
@costela costela requested a review from Copilot June 26, 2026 19:06

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR reduces cross-core contention in the circuit breaker hot path by avoiding unnecessary atomic writes to Circuit.openedAt when the circuit state is already in the desired steady state (closed or open).

Changes:

  • Guard stateObserver.Observe’s open()/close() calls with openedAt.Load() checks to skip redundant atomic writes.
  • Keep the steady-state closed-circuit path read-only when SlidingWindowBreaker.observe repeatedly returns stateChangeClose.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread hoglet.go
Comment on lines +193 to +194
// Only write if not already open. A Load keeps the openedAt cache line in shared state across cores, whereas
// open()'s read-modify-write would needlessly invalidate it on every hot-path call.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants