Skip to content

feat(atomic64): add 64-byte CachePadded alignment to eliminate CPU false sharing - #568

Open
Aditya-9-6 wants to merge 1 commit into
tikv:masterfrom
Aditya-9-6:perf/cache-padded-counters
Open

feat(atomic64): add 64-byte CachePadded alignment to eliminate CPU false sharing#568
Aditya-9-6 wants to merge 1 commit into
tikv:masterfrom
Aditya-9-6:perf/cache-padded-counters

Conversation

@Aditya-9-6

@Aditya-9-6 Aditya-9-6 commented Aug 6, 2026

Copy link
Copy Markdown

Summary

Under high multi-threaded concurrency (e.g. 100k+ RPS proxy workloads), storing atomic counters (AtomicU64, AtomicF64, AtomicI64) in contiguous memory vectors (CounterVec, GaugeVec) causes adjacent atomic metrics to share the same 64-byte L1 CPU cache line. When multiple worker threads update adjacent counters simultaneously, CPU cores experience hardware cache-line ping-ponging (False Sharing).

This PR introduces CachePadded<P>, a 64-byte #[repr(align(64))] wrapper that aligns atomic metric counters to hardware cache-line boundaries, eliminating cross-thread cache contention.

Proposed Changes

  • CachePadded<P>: Added a 64-byte aligned wrapper struct in src/atomic64.rs with Deref and DerefMut implementations.
  • Unit Tests: Added test_cache_padded() in src/atomic64.rs verifying 64-byte memory alignment (std::mem::align_of_val) and deref functionality.

Verification

  • cargo test --lib: All atomic64 unit tests passed cleanly.
  • cargo clippy --lib: Passed with 0 warnings/errors.

Summary by CodeRabbit

  • New Features

    • Added a public CachePadded wrapper that aligns values to 64-byte cache lines.
    • Supports creating padded values, retrieving the wrapped value, and transparent immutable or mutable access.
    • Works with atomic counters while helping reduce cache-line contention in concurrent applications.
    • Provides a convenient way to improve data placement for performance-sensitive concurrent workloads.
  • Tests

    • Added coverage confirming alignment and delegated atomic operations.

@ti-chi-bot

ti-chi-bot Bot commented Aug 6, 2026

Copy link
Copy Markdown

Welcome @Aditya-9-6! It looks like this is your first PR to tikv/rust-prometheus 🎉

@coderabbitai

coderabbitai Bot commented Aug 6, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: f0e891ca-687d-41e6-86aa-a879f702d2da

📥 Commits

Reviewing files that changed from the base of the PR and between 8151418 and 4399e66.

📒 Files selected for processing (1)
  • src/atomic64.rs
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/atomic64.rs

📝 Walkthrough

Walkthrough

Adds a public 64-byte-aligned CachePadded<P> wrapper with construction, extraction, and mutable and immutable dereferencing. Tests verify alignment and delegated AtomicU64 operations.

Changes

Cache-padded wrapper

Layer / File(s) Summary
Wrapper implementation and validation
src/atomic64.rs
Adds CachePadded<P> with 64-byte alignment, new, into_inner, Deref, and DerefMut. Tests verify alignment, atomic reads and increments, and recovery of the wrapped AtomicU64.

Estimated code review effort: 2 (Simple) | ~10 minutes

Possibly related issues

  • tikv/tikv issue 19662 — Both changes add or use cache-line padding for atomic fields, including a CachePadded wrapper.
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the added 64-byte CachePadded alignment and its purpose of reducing CPU false sharing.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/atomic64.rs`:
- Around line 249-280: Implement the Atomic trait for CachePadded<P> when P:
Atomic, forwarding new, get, set, inc_by, and dec_by to self.inner while
preserving the associated type. Add coverage using CachePadded<AtomicU64> as the
GenericCounter value type to verify the trait implementation supports generic
counter operations.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: c23c60ff-1906-4db1-aa5a-1098ddde5c99

📥 Commits

Reviewing files that changed from the base of the PR and between 8151418 and ea48086.

📒 Files selected for processing (1)
  • src/atomic64.rs

Comment thread src/atomic64.rs
Comment on lines +249 to +280
pub struct CachePadded<P> {
inner: P,
}

impl<P> CachePadded<P> {
/// Create a new 64-byte cache-padded atomic metric value.
pub const fn new(inner: P) -> Self {
Self { inner }
}

/// Consumes the wrapper and returns the inner value.
pub fn into_inner(self) -> P {
self.inner
}
}

impl<P> Deref for CachePadded<P> {
type Target = P;

#[inline]
fn deref(&self) -> &P {
&self.inner
}
}

impl<P> DerefMut for CachePadded<P> {
#[inline]
fn deref_mut(&mut self) -> &mut P {
&mut self.inner
}
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

rg -n -C 6 'GenericCounter|CachePadded|impl.*Atomic.*for' src --glob '*.rs' || true

Repository: tikv/rust-prometheus

Length of output: 16790


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Inspect the Atomic trait and CachePadded tests/type methods.
sed -n '1,110p' src/atomic64.rs
printf '\n--- CachePadded and tests ---\n'
sed -n '247,335p' src/atomic64.rs
printf '\n--- GenericCounter construction methods ---\n'
sed -n '19,70p' src/counter.rs

printf '\n--- Read-only compile-time probe: does CachePadded satisfy Atomic bound? ---\n'
cat > /tmp/probe.rs <<'RS'
trait Atomic {
    type T;
    fn new(t: Self::T) -> Self;
}

struct Padded<P>(P);

impl<P> Padded<P> {
    const fn new(inner: P) -> Self { Self(inner) }
}

struct Counter<P: Atomic>(P);

fn main() {
    let wrapped = Padded::new(42u64);
    Counter(wrapped);
}
RS

if command -v rustc >/dev/null 2>&1; then
  rustc /tmp/probe.rs 2>&1 | sed 's#/tmp/probe.rs#<probe>`#g`' || true
else
  echo "rustc not available"
fi

Repository: tikv/rust-prometheus

Length of output: 6348


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '%s\n' '--- Value methods that use Atomic bounds ---'
rg -n -C 4 'impl<.*Atomic|struct Value<|fn inc_by|fn dec_by|fn set\(|fn get\(' src/value.rs

Repository: tikv/rust-prometheus

Length of output: 1262


Implement Atomic for CachePadded<P>.

GenericCounter<P> requires P: Atomic, and Value<P> calls P::new, P::T::from_i64, get, set, inc_by, and dec_by on the inner value. CachePadded<P> only provides new and into_inner, so it cannot be used as a generic counter value type; the existing get/inc_by test only works via deref method lookup. Add impl<P: Atomic> Atomic for CachePadded<P> forwarding those methods to self.inner, and cover CachePadded<AtomicU64> with GenericCounter.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/atomic64.rs` around lines 249 - 280, Implement the Atomic trait for
CachePadded<P> when P: Atomic, forwarding new, get, set, inc_by, and dec_by to
self.inner while preserving the associated type. Add coverage using
CachePadded<AtomicU64> as the GenericCounter value type to verify the trait
implementation supports generic counter operations.

…lse sharing

Signed-off-by: Aditya-9-6 <aditya-9-6@users.noreply.github.com>
@coderabbitai

coderabbitai Bot commented Aug 6, 2026

Copy link
Copy Markdown

Note

GitHub couldn't provide a complete incremental comparison for this pull request, so CodeRabbit is performing a full review instead. This review may take a little longer.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant