我在Internet上看到应该使用System.nanoTime(),但这对我不起作用-它为我提供了毫秒级的时间。我只需要函数执行前后的微秒,就可以知道需要多长时间。我正在使用Windows XP。
基本上,我有这段代码,例如,在Java链表中进行了1百万个到1000万个插入。问题是我无法正确测量精度;有时,花费较少的时间将所有内容插入较小的列表中。
这是一个例子:
class test
{
public static void main(String args[])
{
for(int k=1000000; k<=10000000; k+=1000000)
{
System.out.println(k);
LinkedList aux = new LinkedList();
//need something here to see the start time
for(int i=0; i
aux.addFirst(10000);
//need something here to see the end time
//print here the difference between both times
}
}
}
我做了很多次-每个k有20次外部循环-但是结果不好。有时,进行一千万次插入所需的时间少于一百万次,因为使用当前使用的时间我无法获得正确的测量时间(System.nanoTime())
编辑2:是的,我正在使用Sun JVM。
编辑3:我可能在代码中做错了什么,我会看看更改是否符合我的要求。
编辑4:我的错误,似乎System.nanoTime()有效。唷。
什么版本的Java?在具有JDK1.6.0_06的XP机器上,nanoTime()的精度一直到最后一位小数。我假设您的版本返回的值始终以三个零结尾。
Sun JVM是不够的,它是哪个VERSION? (您的回答是正确的,我没有提出正确的问题。我假设每个人都使用Sun JVM)
cmd中的Java -version给我:Java版本" 1.7.0-ea"和另外2行。无论哪种方式,这都是我的代码中的错误。抱歉,即使搜索了一段时间我也找不到错误。
勇敢的灵魂,1.7仍然很早
自OT开始添加评论。您应该阅读如何编写JVM的微基准测试,例如concentric.net/~ttwang/tech/microbench.htm。此外,您可能希望将10000个整数放在循环外。
要求微秒精度的基准不会非常准确。如果网络上的另一台计算机恰巧对您的设备执行ping操作,或者移动鼠标等,您可以在微秒级的时间测量中增加噪声,而CPU负担最少。
这不能回答您的特定问题,但是使用它可能使它变得不必要:code.google.com/p/caliper
我的猜测是,由于System.nanoTime()使用了"最精确的可用系统计时器",该计时器显然在系统上只有毫秒精度,因此您无法得到更好的结果。
对我来说,尚不清楚您要进行基准测试的确切信息,但总的来说,任何需要花费如此短时间才能运行且精度低于50 ms的测试都将很容易受到其他干扰。
我通常会尝试使基准测试至少运行10秒钟。我目前正在编写的框架将猜测要运行多少次迭代,因此将花费30秒。这意味着您不会因为某些其他进程窃取了CPU几毫秒而获得根本不同的结果。
与尝试以更细粒度的精度进行测量相比,长时间运行几乎总是一种更好的方法。
System.nanoTime()在CPU中使用一个计数器,在Windows XP和Linux中通常精确到大约1微秒。
注意:Windows XP在多cpu机器上通常精度较差,因为它不能补偿具有不同计数器的不同CPU。 Linux确实如此。
注意2:它会相对于System.currentTimeMillis()漂移,因为它基于CPU时钟的准确性(一段时间内不需要那么精确),而不是您拥有的时钟来获取时间(每天漂移较少,但粒度较小)
在基准测试中,您基本上正在测试创建新对象的速度。毫不奇怪,根据您的GC设置以及最近执行一次GC的结果,您的结果将发生巨大变化。
尝试使用以下选项运行测试,您将看到非常不同的结果。
-verbosegc -XX:NewSize=128m -mx256m
使用java.time
FYI,Java 9和更高版本具有Clock的全新实现,可以以高达纳秒的分辨率捕获当前时刻。
Instant类表示UTC时间轴上的时刻,其分辨率为纳秒(最多十进制的九(9)位数字)。
调用Instant.now捕获当前时刻。
在Java 9和更高版本中,当前时刻的分辨率最高为纳秒。
在Java 8中,当前时刻最多只能捕获到毫秒级的分辨率(您确实可以保留纳秒级的值,但只能捕获到毫秒级的当前时刻)。
Instant Instant = Instant.now();
用Duration类表示未附加到时间轴的时间跨度。保留时间量(以秒和纳秒为单位)。
Duration d = Duration.between( instantThen , Instant.now() );
明确地说,问题中要求的微秒分辨率介于毫秒和纳秒之间。十进制小数位数:毫秒为3(0.123),微米为6(0.123456),纳米为9(0.123456789)。
警告
Java依赖于计算机的硬件时钟。正如其他人警告的那样,硬件几乎可以肯定会以比纳秒低得多的精度和更低的分辨率捕获时间。
如此细粒度的基准测试存在很多问题,通常不建议这样做。
并提防过早的优化。
有人建议在JEP 230:Microbenchmark Suite中向Java平台添加微基准测试功能。基于Java Microbenchmark Harness(JMH)。
关于java.time
java.time框架内置于Java 8及更高版本中。这些类取代了麻烦的旧旧式日期时间类,例如java.util.Date,Calendar和SimpleDateFormat。
现在处于维护模式的Joda-Time项目建议迁移到java.time类。
要了解更多信息,请参见Oracle教程。并在Stack Overflow中搜索许多示例和说明。规格为JSR 310。
在哪里获取java.time类?
Java SE 8和SE 9及更高版本
内置。
标准Java API的一部分,具有捆绑的实现。
Java 9添加了一些次要功能和修复。
Java SE 6和SE 7
java.time的许多功能在ThreeTen-Backport中都被反向移植到Java 6和7。
Android的
ThreeTenABP项目专门针对Android改编了ThreeTen-Backport(如上所述)。
请参阅如何使用ThreeTenABP…。
ThreeTen-Extra项目使用其他类扩展了java.time。该项目为将来可能在java.time中添加内容提供了一个试验场。您可能会在这里找到一些有用的类,例如Interval,YearWeek,YearQuarter等。
如果想要可靠的结果,请使用分析器。我建议使用VisualVM,它易于安装,并且从1.6.0_07版本开始与JDK捆绑在一起。
这是一个易于使用的可视化工具,集成了多个命令行JDK工具和轻量级分析功能。
您必须重复测试数千次。有很多事情会影响您的测量,例如垃圾收集,I / O,交换/交换,就绪队列线程的大小等。
这很奇怪。 System.nanoTime()应该可以工作。您正在使用Sun JVM吗?
您是否可以重复操作1000次,然后将时间除以1000,以找出需要了解的内容?
是的,System.nanoTime的准确性和精确度通常比System.currentTimeMillis更好,但是并不能保证:在最坏的情况下,它也同样会变得很糟糕。
ThreadMXBean.getCurrentThreadCpuTime倾向于产生更短的时间,但是其分辨率尚不清楚,并且还具有其他缺点(您是否真的需要CPU时间?平台依赖的语义,平台是否支持?)。
用这三种技术测量时间也有一些成本,即需要时间本身,这会使测量值失真。成本与平台高度相关,但通常成本(System.currentTimeMillis)<
关于一般的微基准测试,请参阅
如何在Java中编写正确的微基准测试?
使用Java创建快速/可靠的基准测试?
底层操作系统可能不提供具有纳秒级精度的计时器。
还有一个较旧的帖子。
对于我们最近的分析,我发现ThreadMXBean.getCurrentThreadCpuTime()和选项-XX:+UseLinuxPosixThreadCPUClocks满足了我们的需求。
有关更多详细信息,请参见http://bugs.java.com/view_bug.do?bug_id=6888526
我最终使用的"快速而肮脏的"解决方案:
TimeUnit.NANOSECONDS.toMicros(System.nanoTime());
更新:
我最初使用System.nanoTime,但是后来我发现它仅应用于经过的时间,最终我更改了代码以使其可以使用毫秒或在某些地方使用:
TimeUnit.MILLISECONDS.toMicros(System.currentTimeMillis());
但这只会在值的末尾添加零(微秒=毫秒* 1000)
如果有人想到nanoTime,则将此答案留在此处作为"警告信号" :)
这种依赖短时间间隔的基准会给您带来不可靠的结果。由于I / O,交换,进程切换,高速缓存,垃圾回收等外部因素,您总是会得到不同的结果。此外,JVM优化了您的调用,因此最先进行测量的事情可能会比以后的调用慢。 JVM越来越多地开始优化您执行的命令。
另外,类似System.nanoTime()的方法取决于基础系统的计时器。他们可能(而且很可能会)没有粒度来测量该准确性。引用API:
This method provides nanosecond
precision, but not necessarily
nanosecond accuracy. No guarantees are
made about how frequently values
change.
要真正进行高精度测量,您需要使用保证精度的外部计时硬件。
为了使基准更加稳定,您需要执行多次,并且测量的时间间隔要大于毫秒。