System.currentTimeMillis()的性能问题

一直觉得java原生API都是性能很高的,今天看一篇博客时,说到System.currentTimeMillis()的性能十分低下,觉得很奇怪,于是写了一些代码来尝试了一下

public class CurrentTimeTest {
    private static final int COUNT = 100;
    public static void main(String[] args) throws Exception {
        long beginTime = System.nanoTime();
        for (int i = 0; i < COUNT; i++) {
            System.currentTimeMillis();
        }
        long elapsedTime = System.nanoTime() - beginTime;
        System.out.println("单线程100次   System.currentTimeMillis : " + elapsedTime + " ns");
        CountDownLatch startLatch = new CountDownLatch(1);
        CountDownLatch endLatch = new CountDownLatch(COUNT);
        for (int i = 0; i < COUNT; i++) {
            new Thread(() -> {
               try {
                   startLatch.await();
                   System.currentTimeMillis();
               } catch (InterruptedException e) {
                   e.printStackTrace();
               } finally {
                   endLatch.countDown();
               }
            }).start();
        }
        beginTime = System.nanoTime();
        startLatch.countDown();
        endLatch.await();
        elapsedTime = System.nanoTime() - beginTime;
        System.out.println("100线程并发下 System.currentTimeMillis : " + elapsedTime + " ns");
    }
}

执行结果如下:

可见System.currentTimeMoillis一百次耗费的时间非常大,尤其是并发状态下比单线程高出一个量级,甚至极端情况比创建对象更耗费资源

查看HotSpot源码的hotspot/src/os/linux/vm/os_linux.cpp,有一个javaTimeMillis方法,这就是System.currentTimeMillis的native实现。

jlong os::javaTimeMillis {
    timeval time;
    int status = gettimeofday(&time, NULL);
    assert(status != -1, "linux error");
    return jlong(time.tv_sec) * 1000 + jlong(time.tv_usec / 1000);
}

对于这部分源码已经有国外大佬深入到了汇编的级别来探究,详情可以参见《The Slow currentTimeMillis》

简单来讲就是:
    1.调用gettimeofday需要从用户态切换到内核态;
    2.gettimeofday的表现受Linux系统的计时器(时钟源)影响,在HPET计时器下性能尤其差;
    3.系统只有一个全局时钟源,高并发或频繁访问会造成严重的争用。

HPET计时器性能较差的原因是会将所有对时间戳的请求串行执行。TSC计时器性能较好,因为有专用的寄存器来保存时间戳。缺点是可能不稳定,因为它是纯硬件的计时器,频率可变(与处理器的CLK信号有关)。关于HPET和TSC的细节可以参见下面的链接,就不做过多讨论
https://en.wikipedia.org/wiki/HighPrecisionEventTimer
https://en.wikipedia.org/wiki/TimeStamp_Counter。

猜你喜欢

转载自www.cnblogs.com/gtblog/p/12698977.html