Skip to content

[SDK] Replace SpinLockMutex with std::mutex in the metrics library - #4416

Open
dbarker wants to merge 4 commits into
open-telemetry:mainfrom
dbarker:sdk_swap_spinlock_for_mutex_part_2
Open

[SDK] Replace SpinLockMutex with std::mutex in the metrics library#4416
dbarker wants to merge 4 commits into
open-telemetry:mainfrom
dbarker:sdk_swap_spinlock_for_mutex_part_2

Conversation

@dbarker

@dbarker dbarker commented Aug 11, 2026

Copy link
Copy Markdown
Member

Fixes #4317

Part 2 of #4317 to replace SpinLockMutex with std::mutex.

This PR replaces all use of the SpinLockMutex in the metrics sdk. The goal is to improve synchronization consistency across platforms and deployments by relying on the standard mutex.

Changes

  • Replaces SpinLockMutex with std::mutex in the metrics library.

For significant contributions please make sure you have completed the following items:

  • CHANGELOG.md updated for non-trivial changes
  • Unit tests have been added
  • Changes in public API reviewed

@codecov

codecov Bot commented Aug 12, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 82.69%. Comparing base (4aee171) to head (ceed5d5).

Additional details and impacted files

Impacted file tree graph

@@           Coverage Diff           @@
##             main    #4416   +/-   ##
=======================================
  Coverage   82.69%   82.69%           
=======================================
  Files         505      505           
  Lines       19933    19933           
=======================================
  Hits        16482    16482           
  Misses       3451     3451           
Files with missing lines Coverage Δ
...ry/sdk/metrics/aggregation/histogram_aggregation.h 90.48% <ø> (ø)
...ry/sdk/metrics/aggregation/lastvalue_aggregation.h 0.00% <ø> (ø)
...elemetry/sdk/metrics/aggregation/sum_aggregation.h 0.00% <ø> (ø)
...telemetry/sdk/metrics/state/async_metric_storage.h 93.19% <100.00%> (ø)
...ntelemetry/sdk/metrics/state/sync_metric_storage.h 84.94% <ø> (ø)
...egation/base2_exponential_histogram_aggregation.cc 96.63% <100.00%> (ø)
...k/src/metrics/aggregation/histogram_aggregation.cc 88.89% <100.00%> (ø)
...k/src/metrics/aggregation/lastvalue_aggregation.cc 82.26% <100.00%> (ø)
sdk/src/metrics/aggregation/sum_aggregation.cc 80.00% <100.00%> (ø)
sdk/src/metrics/state/sync_metric_storage.cc 93.69% <100.00%> (ø)
... and 1 more
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.


private:
mutable opentelemetry::common::SpinLockMutex lock_;
mutable std::mutex lock_;

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I've made the swap to std::mutex here also to be consistent throughout the SDK. This use case for sum aggregation could be a good use for a spinlock but testing showed it was ~10ns difference with the mutex in the uncontested case. This performance delta is not significant compared to the attribute hash map lookup.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

The attribute-map comparison makes sense for the unbound path, but the bound path skips that lookup. It now takes the BoundEntry mutex and then this mutex for every sum update, so the reported 10 ns may matter more there.

Could we capture before-and-after results for the existing bound and unbound counter benchmarks, including a contended case? Since #4317 originally kept this spinlock and requested benchmarks for part 2, I think we should have that evidence before changing this hot path.

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.

This could increase memory usage significantly. Measured with MSVC x64 but it should similar for Linux.

type before (bytes) after (bytes)
LongSumAggregation 40 112
LongLastValueAggregation 48 120
LongHistogramAggregation 136 208

The driver is that sizeof(std::mutex) is 80 bytes on MSVC and 40 on glibc, while sizeof(std::atomic<bool>) is 1. One aggregation object is allocated per time series, and the default cardinality limit is 2000. That alone is 2000 x 72 = ~144 KB extra per counter instrument. TemporalMetricStorage keeps a per-collector stash of previously reported aggregations, so a configuration with one reader roughly doubles it, reaching near 300 KB per instrument.

@dbarker
dbarker marked this pull request as ready for review August 12, 2026 16:14
@dbarker
dbarker requested a review from a team as a code owner August 12, 2026 16:14
MetricAttributes attrs_copy;
{
std::lock_guard<opentelemetry::common::SpinLockMutex> g(entry->lock_);
std::lock_guard<std::mutex> g(entry->lock_);

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.

The above comments still says spinlock while it has chanegd to std::mutex.

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.

Proposal: Replace SpinLockMutex with std::mutex where appropriate

3 participants