我目前正在为我所在大学的研究所工作Stroop Test。
虽然测量用户需要按键的时间没有问题,但我很好奇当我打电话给System.nanoTimes()
时会出现什么样的延迟。我写了一个小测试
@Test
public void nanoTest()
{
for(int i = 0; i < 100; i++)
{
long t1 = System.nanoTime();
long t2 = System.nanoTime();
long t3 = System.nanoTime();
System.out.println("took: "+(t3-t1));
}
}
告诉我:
took: 513
took: 0
took: 513
took: 513
took: 0
took: 0
took: 0
took: 0
took: 0
took: 514
took: 0
... etc.
除了0,513或514之外没有其他值。如果我用long t2 = System.nanoTime();
替换long t2 = System.currentTimeMillis();
,它将打印类似
took: 1540
took: 513
took: 513
took: 0
took: 0
took: 514
took: 514
took: 513
took: 513
took: 513
took: 514
... etc.
我假设第一次调用System.currentTimeMillis()
函数没有被缓存(我不确定JVM如何处理缓存......)因此延迟比通常的0.5ms大。我可以假设这是因为函数被缓存并经常被调用。虽然我在调用nanoTimes()
时延迟0到0.5毫秒之间没什么问题,但是对于调用时间函数我有1.5毫秒甚至更长时间。
我可以告诉JVM甚至我的cpu缓存特定的时间函数吗?我可以告诉JVM可能缓存整个程序吗?如何在测量时间的同时实现最小的延迟?
我知道这些数字可能因PC而异,如果我在后台运行更多程序,甚至会有所不同,因此我尝试在时间测量中获得最小的延迟。
答案 0 :(得分:2)
System.nanoTime不保证纳米时间准确度:
http://docs.oracle.com/javase/6/docs/api/java/lang/System.html#nanoTime%28%29
该方法提供纳秒精度,但不一定是纳秒精度。不保证值的变化频率。
波动可能仅仅来自时钟粒度,线程调度等因素。对如此小的间隔进行基准测试很难准确,通常不值得努力。
答案 1 :(得分:1)
我建议你考虑将反应测试链接到可以取平均值的点,以便减少小故障。 例如。对于100ms左右的测量,我认为+/- 0.5ms不重要。
但是,如果你真的需要那种精确度,那么你的工具(Java和标准计算机,我猜)可能还不够。通常,您还必须考虑外围设备的输入延迟等方面,当然还有显示滞后(现代显示器仍然至少有1-2毫秒)。 当然 系统的系统达到亚微秒精度以进行实际交互,但这些系统是高度专业化的,并没有广泛使用。
答案 2 :(得分:0)
将System.currentTimeMillis()
替换为Clock.getRealtimeClock().currentTimeMillis()
。
第一次延迟是不可避免的,因为将功能加载到堆栈本身需要一些时间。我相信没有方法缓存的概念。如果我错了,有人会纠正我。