-
Notifications
You must be signed in to change notification settings - Fork 31
Description
File: LongConcurrentHistogram.cs
protected override void IncrementCountAtIndex(int index)
{
long criticalValue = _wrp.WriterCriticalSectionEnter();
try
{
_counts.IncrementAndGet(index); // Interlocked.Add
Interlocked.Increment(ref _totalCount); // second atomic op
}
finally { _wrp.WriterCriticalSectionExit(criticalValue); }
}
Every RecordValue call in the concurrent histogram pays for WriterCriticalSectionEnter (an Interlocked.Increment), Interlocked.Add on the count, Interlocked.Increment on _totalCount, and WriterCriticalSectionExit (another Interlocked.Increment). That's four atomic operations per record.
_totalCount is only read by TotalCount which already calls Interlocked.Read. Consider whether _totalCount needs to be updated atomically at all during recording, or whether it can be derived lazily by summing the array (expensive) or maintained with a Volatile.Write (cheaper). The Java original avoids this cost by using a single updater CAS. A Recorder-pattern approach (per-thread histograms merged on read) avoids the issue entirely and is the recommended usage pattern anyway.