我现在正在尝试编写简单的渲染器,它将以 60Hz 的频率调用渲染方法并 hibernate 额外的时间来为其他人节省 CPU 周期。
我遇到了一个简单的问题
while(m_Running){
//start meassuring whole frame time
t0 = System.nanoTime();
render();
//meassure time spent rendering
t1 = System.nanoTime();
if(t1<nextRedraw){
try{
diff = nextRedraw-t1;
ms = diff/1000000;
ns = (int) (diff-(ms*1000000));
Thread.sleep(ms, ns);
}catch(InterruptedException e){
Logger.logWarning("Renderer interrupted!",e);
}
//while(System.nanoTime()<nextRedraw);//busy wait alternative
}
//meassure time spent sleeping
t2 = System.nanoTime();
nextRedraw = t2+m_RedrawTimeout;
long frameTime = t2-t0;
long renderTime = t1-t0;
long sleepTime = t2-t1;
long fps = 1000000000/frameTime;
}
运行良好,但与预期的 60fps 相去甚远,而是在值之间跳跃
FPS: 63 Frame: 15,7ms Render: 2,0ms Sleep: 13,7ms
FPS: 64 Frame: 15,5ms Render: 2,0ms Sleep: 13,5ms
FPS: 63 Frame: 15,7ms Render: 2,1ms Sleep: 13,5ms
FPS: 59 Frame: 16,7ms Render: 2,8ms Sleep: 14,0ms
FPS: 64 Frame: 15,5ms Render: 2,2ms Sleep: 13,3ms
当我尝试改用忙等待时,结果更加一致并且更接近我想要的 fps 目标。
FPS: 60 Frame: 16,4ms Render: 2,0ms Sleep: 14,5ms
FPS: 60 Frame: 16,4ms Render: 2,0ms Sleep: 14,4ms
FPS: 60 Frame: 16,4ms Render: 2,0ms Sleep: 14,4ms
FPS: 61 Frame: 16,3ms Render: 2,4ms Sleep: 13,8ms
FPS: 61 Frame: 16,3ms Render: 2,1ms Sleep: 14,2ms
FPS: 60 Frame: 16,4ms Render: 2,0ms Sleep: 14,4ms
不过,我想避免这种情况,因为这是可以理解的 CPU 缺点。我想到了一个想法,让 sleep 时间比必要的少一点,并精确地遍历剩余时间,但这似乎有点笨拙。
我的问题是,编译器是否以某种方式优化了忙等待,或者是否有其他方法可以达到类似的时序?
如有任何帮助,我们将不胜感激。
谨致问候,
沃伊捷赫
注意:我使用了 System.nanoTime();为了使事情更准确,它没有帮助,但我不知道它有任何性能缺陷
注意:我知道 sleep 很不准确,但我没有找到任何其他替代方法
最佳答案
我想,时间上的微小差异可能会加起来更大,您可以通过使 sleep 取决于总时间来轻松避免这种情况。
有点像
long basetime = System.nanoTime();
for (int i=0; m_Running; ++i) {
...
nextRedraw = baseTime + i * m_RedrawTimeout;
}
如果当前 sleep 太短,这应该会使后续 sleep 更短,反之亦然,因此您获得的 FPS 最多仅每秒变化几毫秒(即 < 1%)。
也许没有问题,只是你衡量的是单帧需要多长时间。这个数字略有不同,并没有说明 FPS 速率。
据我所知,Thread.sleep
中的纳秒被完全忽略。
关于java - 忙碌的等待, sleep 和准确性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27305587/