Skip to content

LongConcurrentHistogram.IncrementCountAtIndex — Two Atomic Operations Where One Suffices #148

@leecampbell-codeagent

Description

@leecampbell-codeagent

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions