大家都知道线程切换的开销很大,所有要使用线程池。那么这个开销到底包含哪些?到底有多大呢?特别是切换的时间是什么量级的。
首先在网上搜了一下,看到一片文章,提到一次context switch的耗时是在10Kns的量级上,也就是0.01ms。感觉还是挺大的了, 那么我们如何自己测量一下呢?
  处理器名称:	Intel Core i7
  处理器速度:	2.2 GHz
  处理器数目:	1
  核总数:	    6
  L2 缓存(每个核):	256 KB
  L3 缓存:	    9 MB
不严谨的测量是很简单的,利用LockSupport提供的park和unpark就很简单能做个实验。
  final AtomicLong cost = new AtomicLong(0);
        final AtomicLong count = new AtomicLong(0);
        final AtomicLong beforeUnpark = new AtomicLong(0);

        final CyclicBarrier barrier = new CyclicBarrier(2);

        Thread thread = new Thread(() -> {
            for (int i = 0; i < 1000; i++) {
                try {
                    barrier.await();
                } catch (InterruptedException | BrokenBarrierException e) {
                    e.printStackTrace();
                }
                LockSupport.park();
                long delta = System.nanoTime() - beforeUnpark.get();
                cost.addAndGet(delta);
                System.out.println("cost: " + delta);
                count.incrementAndGet();
            }
        });
        thread.start();

        for (int i = 0; i < 1000; i++) {
            barrier.await();
            Thread.sleep(100);
            barrier.reset();
            beforeUnpark.set(System.nanoTime());
            LockSupport.unpark(thread);
        }

        System.out.println("avg: " + (cost.get() / count.get()));
测试的结果大概是40000 ns左右,和上面文章提到的数据比较相符。其实context switch最大成本应该是 cache pollution。
参考:
  1. https://blog.takipi.com/java-thread-magic-tricks/
  2. https://blog.tsunanet.net/2010/11/how-long-does-it-take-to-make-context.html
  3. https://en.wikipedia.org/wiki/Processor_affinity
  4. https://stackoverflow.com/questions/6987394/how-can-you-measure-the-time-spent-in-a-context-switch-under-java-platform