java concurrency: many writers, one reader

前端 未结 9 2090
我寻月下人不归
我寻月下人不归 2021-01-30 18:22

I need to gather some statistics in my software and i am trying to make it fast and correct, which is not easy (for me!)

first my code so far with two classes, a StatsS

9条回答
  •  后悔当初
    2021-01-30 19:08

    Here is how to do it with minimal impact on the performance of the threads being measured. This is the fastest solution possible in Java, without resorting to special hardware registers for performance counting.

    Have each thread output its stats independently of the others, that is with no synchronization, to some stats object. Make the field containing the count volatile, so it is memory fenced:

    class Stats
    {
       public volatile long count;
    }
    
    class SomeRunnable implements Runnable
    {
       public void run()
       {
         doStuff();
         stats.count++;
       }
    }
    

    Have another thread, that holds a reference to all the Stats objects, periodically go around them all and add up the counts across all threads:

    public long accumulateStats()
    {
       long count = previousCount;
    
       for (Stats stat : allStats)
       {
           count += stat.count;
       }
    
       long resultDelta = count - previousCount;
       previousCount = count;
    
       return resultDelta;
    }
    

    This gatherer thread also needs a sleep() (or some other throttle) added to it. It can periodically output counts/sec to the console for example, to give you a "live" view of how your application is performing.

    This avoids the synchronization overhead about as much as you can.

    The other trick to consider is padding the Stats objects to 128 (or 256 bytes on SandyBridge or later), so as to keep the different threads counts on different cache lines, or there will be caching contention on the CPU.

    When only one thread reads and one writes, you do not need locks or atomics, a volatile is sufficient. There will still be some thread contention, when the stats reader thread interacts with the CPU cache line of the thread being measured. This cannot be avoided, but it is the way to do it with minimal impact on the running thread; read the stats maybe once a second or less.

提交回复
热议问题