码迷,mamicode.com
首页 > 其他好文 > 详细

System.nanoTime()和System.currentTimeMillis()性能问题

时间:2018-06-26 00:58:29      阅读:955      评论:0      收藏:0      [点我收藏+]

标签:interval   win   exce   cep   并发   ble   new   average   时间源   

  之前给模块做性能优化的时候,需要将性能调到毫秒级,使用了System.nanoTime()和System.currentTimeMillis()对代码分片计时分析耗时操作,后发现在串行情况下性能达到毫秒级,但是一旦在并发压测的时候,性能急剧下降,后经多方排查,发现原因出在System.nanoTime()和System.currentTimeMillis()这两个api上,其在并发情况下耗时会急剧上升,当然在整体上看依然很快,但是在高性能场景下就有很显著的影响。特此记录一下。

  测试代码:

 1 package cord;
 2 
 3 import java.util.concurrent.CountDownLatch;
 4 
 5 /**
 6  * Created by cord on 2018/5/7.
 7  */
 8 public class SystemApiPerfTest {
 9 
10     public static void main(String[] args) throws InterruptedException {
11         int count = 100;
12         /**并发*/
13        long interval = concurrentTest(count, ()->{System.nanoTime();});
14        System.out.format("[%s] thread concurrent test <nanoTime> cost total time [%s]ns, average time [%s]ns.\n", count, interval, interval/count);
15 
16        /**串行循环*/
17        interval = serialNanoTime(count);
18        System.out.format("[%s] count serial test <nanoTime> cost total time [%s]ns, average time [%s]ns.\n", count, interval, interval/count);
19 
20        System.out.println("-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-");
21 
22         /**并发*/
23         interval = concurrentTest(count, ()->{System.currentTimeMillis();});
24         System.out.format("[%s] thread concurrent test <currentTimeMillis> cost total time [%s]ns, average time [%s]ns.\n", count, interval, interval/count);
25 
26         /**串行循环*/
27         interval = serialCurrentTime(count);
28         System.out.format("[%s] count serial test <currentTimeMillis> cost total time [%s]ns, average time [%s]ns.\n", count, interval, interval/count);
29 
30     }
31 
32     private static long concurrentTest(int threads, final Runnable r) throws InterruptedException {
33         final CountDownLatch start = new CountDownLatch(1);
34         final CountDownLatch end = new CountDownLatch(threads);
35 
36         for (int i = 0; i < threads; i++) {
37             new Thread(() -> {
38                 try {
39                     start.await();
40                     try {
41                         r.run();
42                     }finally {
43                         end.countDown();
44                     }
45                 } catch (InterruptedException e) {
46                     e.printStackTrace();
47                 }
48             }).start();
49         }
50 
51         long stime = System.nanoTime();
52         start.countDown();
53         end.await();
54         return System.nanoTime() - stime;
55     }
56 
57     private static long serialNanoTime(int count){
58         long stime = System.nanoTime();
59         for (int i = 0; i < count; i++) {
60             System.nanoTime();
61         }
62         return System.nanoTime() - stime;
63     }
64 
65     private static long serialCurrentTime(int count){
66         long stime = System.nanoTime();
67         for (int i = 0; i < count; i++) {
68             System.currentTimeMillis();
69         }
70         return System.nanoTime() - stime;
71     }
72 }

测试结果如下:

[100] thread concurrent test <nanoTime> cost total time [5085539]ns, average time [50855]ns.
[100] count serial test <nanoTime> cost total time [2871]ns, average time [28]ns.
-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
[100] thread concurrent test <currentTimeMillis> cost total time [7678769]ns, average time [76787]ns.
[100] count serial test <currentTimeMillis> cost total time [4103]ns, average time [41]ns.

串行情况下耗时趋于稳定,但是在并行情况下就不一样了。

因为这两个api都是native方法,涉及到系统层级的调用,与平台有关。

主要原因有两点:

  1. JVM使用gettimeofday()而不是clock_gettime()来获取时间戳;
  2. 如果使用HPET时间源,gettimeofday()速度非常慢

除此之外,同样的api,在windows平台的性能比linux上快。

具体原因与实现细节可参阅下面这篇文章(可能需要梯子):

http://pzemtsov.github.io/2017/07/23/the-slow-currenttimemillis.html

System.nanoTime()和System.currentTimeMillis()性能问题

标签:interval   win   exce   cep   并发   ble   new   average   时间源   

原文地址:https://www.cnblogs.com/cord/p/9226676.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!