System.nano()详解

System.nanoTime只能用于计算时间差,不能用于计算时间的准确度(System.out.println(new Date(System.nanoTime()));这种是绝对错误的)。

Returns the current value of the most precise available system timer, in nanoseconds.

This method can only be used to measure elapsed time and is not related to any other notion of system or wall-clock time. The value returned represents nanoseconds since some fixed but arbitrary time (perhaps in the future, so values may be negative). This method provides nanosecond precision, but not necessarily nanosecond accuracy. No guarantees are made about how frequently values change. Differences in successive calls that span greater than approximately 292 years (263 nanoseconds) will not accurately compute elapsed time due to numerical overflow.

For example, to measure how long some code takes to execute:

1.long startTime = System.nanoTime();   
2.// ... the code being measured ...   
3.long estimatedTime = System.nanoTime() - startTime;

 

2) Java中的System.nano()很慢

 

 System.nano()调用耗时450 nano,超级慢,比new Object()的操作慢100倍。比System.currentMillis()慢20多倍。

经一群无聊好事者查证,System.nanoTime()在linux下的实现,最终调用clock_gettime系统函数。

100万次调用耗时,java语言中System.nanoTime()和C语言中的clock_gettime()调用时间基本一致,所以System.nanoTime()慢的原因就是系统调用clock_gettime。

无聊好事者请注意,自行测试System.nanoTime()性能时,要这样写:

 

1.for (int i = 0; i < 1000 * 1000; ++i) {   
2.    long v = System.nanoTime();   
3.}  

 

而不能这样写:

 

1.for (int i = 0; i < 1000 * 1000; ++i) {   
2.    System.nanoTime();   
3.} 

 

上面梁总写法区别:

 

1.public class NanoTimeTest {   
2.    public static void main(String [] args) {   
3.        test1();   
4.        test2();   
5.    }   
6.  
7.    static void test1() {   
8.        long time = System.currentTimeMillis();   
9.        for(int i=0; i < 1000 * 1000; ++i) {   
10.            System.nanoTime();   
11.        }   
12.        System.out.println("test1:" + (System.currentTimeMillis() - time));   
13.    }   
14.  
15.    static void test2() {   
16.        long time = System.currentTimeMillis();   
17.        for(int i=0; i < 1000 * 1000; ++i) {   
18.            long v = System.nanoTime();   
19.        }   
20.        System.out.println("test2:" + (System.currentTimeMillis() - time));   
21.    }   
22.}  

 

F:\Java2>java -server NanoTimeTest
test1:500
test2:500

F:\Java2>java -client NanoTimeTest
test1:16
test2:484 

 

3)

Java5+

摩尔定律是一种众所周知的现象,即计算机中的晶体管数量和它的处理速度随时间呈指数规律增长。作为仙童半导体公司(Fairchild Semiconductor)的研发领导人,戈登•摩尔于1965年提出了这一伟大发现。迄今为止,它仍有效。
与Java首次出现的时候相比,当前计算机的速度要快得多,对于很多应用程序而言以毫秒计时已不再能够满足要求。你可能使用过java.lang.System类,利用currentTimeMillis方法来获得一个方法调用或一段代码的定时信息。此方法可以用来度量执行某操作所花费的时间。但是,在运算速度更快的计算机上操作花费的时间可能远小于1毫秒,于是可以在一个for循环中执行此操作上百次或上千次,然后除以循环次数来计算此操作的单位时间。考虑下面的示例:

 

long startTime = System.currentTimeMillis();
for (int i=0; i<1000; i++) {
performOperation(); // something we want to measure
}
long endTime = System.currentTimeMillis();
long totalTimeInMillis = endTime - startTime;
// because the count was 1000, it's easy to get the unit time
long unitTimeInMicros = totalTimeInMillis; 

 

这种一种很简单的运算,因为使用了for循环1000次。但是如果要度量亚微秒该如何实现呢?

 

for(int i=0; i<1000000; i++) { performOperation(); } 

 

如果从人类的角度来看,可怜的for循环将不得不不厌其烦地百万次的频繁循环!此外,只有在重复执行操作没有副作用的情况下使用for循环来计算时间才是有用的。如果操作是调用java.util.Collections.sort方法,那么将很难计算出排序过程花费的时间。在Java 5中,System类有一个新的nanoTime方法,它能返回一个纳秒精度的计数器。尽管不能将它用于度量绝对时间,但是它能够很好地度量时间差别。

 

List myList = initializeList();  // initialize the List somehow
long startTime = System.nanoTime();
Collections.sort(myList);         // measuring the sort time
long endTime = System.nanoTime();
long differenceInNanoseconds = endTime - startTime; 

 

 

遗憾的是,运行上面的代码时无法保证实际上获得的是纳秒级的度量。但是使用更快的机器和良好的JRE实现,对于测试目的而言它是一种有用的度量方法。可以在JDK 5文档中找到更多有关此方法的信息。鉴于操作系统特性、机器处理速度和系统负载的不同,得到的由nanoTime方法返回的值可能会有很大的变化。随着时间的推移此问题应该会有所改善,摩尔定律基本上能保证这一点。

参考资料:

想要了解摩尔的原始论文,请参看Gordon E. Moore, Cramming More Components onto Integrated Circuits, Electronics, Vol. 38, No. 8 (April 19, 1965)。此外,还可以在网上获得该论文,参看本书的网站http:// wickedcooljava.com以获得URL。

你可能感兴趣的:(System)