Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using LongAdder to calculate a max value for a statistical counter?

We collect some statistics using AtomicLongs. Some users are seeing contention on these and have suggested using LongAdder instead. However I see no way to calculate the maximum value as we are currently doing with the Atomic:

AtomicLong _current, _total, _max;
...

void add(long delta)
{
  long current = _current.addAndGet(delta);
  if (delta>0)
  {
    _total.addAndGet(delta);
    long max = _max.get();
    while (current > max)
    {
      if (_max.compareAndSet(max, current))
        break;
      max = _max.get();
    }
 }

So I think we can replace _total easily enough with a LongAdder, but because we do _current.addAndGet(delta) that will not work well for a LongAdder, nor can we do cas operation for the `_max' value.

Are there any good algorithms for collecting such statistics based on LongAdder or similar scalable lock free constructs?

Actually, whiles I'm asking, our stats typically update 6 to 10 AtomicLongs. If we are seeing contention anyway, could it be possibly be better to just grab a lock and update 6 to 10 normal longs?

like image 281
gregw Avatar asked Apr 01 '16 01:04

gregw


1 Answers

You don't want LongAdder, but LongAccumulator here: you want new LongAccumulator(Math::max, Long.MIN_VALUE), which does the right thing here. LongAdder is a special case of LongAccumulator.

like image 141
Louis Wasserman Avatar answered Nov 01 '22 13:11

Louis Wasserman