我想知道的是在更新我的对象在游戏中的位置时是否应该使用System.currentTimeMillis()或System.nanoTime()?它们的运动变化与自上次呼叫后经过的时间成正比,我希望尽可能精确.
我读过不同的操作系统之间存在一些严重的时间分辨率问题(即Mac/Linux的分辨率几乎为1毫秒,而Windows的分辨率为50毫秒).我主要在Windows上运行我的应用程序,50ms分辨率似乎非常不准确.
有没有比我列出的两个更好的选择?
有什么建议/意见吗?
显然在我的Windows 8笔记本电脑上使用HotSpot JDK 1.7.0_45(所有编译器/ VM选项都设置为默认值),下面的循环
final int n = Integer.MAX_VALUE;
int i = 0;
while (++i < n) {
}
Run Code Online (Sandbox Code Playgroud)
比以下情况快至少2个数量级(~10 ms vs.~5000 ms):
final int n = Integer.MAX_VALUE;
int i = 0;
while (i++ < n) {
}
Run Code Online (Sandbox Code Playgroud)
在编写循环以评估另一个不相关的性能问题时,我碰巧注意到了这个问题.之间的差异++i < n和i++ < n是巨大的,足以显著影响结果.
如果我们查看字节码,更快版本的循环体是:
iinc
iload
ldc
if_icmplt
Run Code Online (Sandbox Code Playgroud)
而对于较慢的版本:
iload
iinc
ldc
if_icmplt
Run Code Online (Sandbox Code Playgroud)
因此++i < n,它首先将局部变量递增i1,然后将其推入操作数堆栈,同时i++ < n以相反的顺序执行这两个步骤.但这似乎并不能解释为什么前者要快得多.后一种情况是否涉及临时副本?或者是否应该负责性能差异的字节码(VM实现,硬件等)以外的东西?
我已经阅读了一些关于++i和i++(但并非详尽无遗)的其他讨论,但未找到任何特定于Java的答案,并且与价值比较中涉及++i或i++涉及的情况直接相关.
java performance compiler-optimization pre-increment post-increment
在写另一个问题的答案时,我注意到JIT优化的一个奇怪的边界情况.
以下程序不是 "Microbenchmark",也不是为了可靠地测量执行时间(如另一个问题的答案中所指出的).它仅用作MCVE来重现该问题:
class MissedLoopOptimization
{
public static void main(String args[])
{
for (int j=0; j<3; j++)
{
for (int i=0; i<5; i++)
{
long before = System.nanoTime();
runWithMaxValue();
long after = System.nanoTime();
System.out.println("With MAX_VALUE : "+(after-before)/1e6);
}
for (int i=0; i<5; i++)
{
long before = System.nanoTime();
runWithMaxValueMinusOne();
long after = System.nanoTime();
System.out.println("With MAX_VALUE-1 : "+(after-before)/1e6);
}
}
}
private static void runWithMaxValue()
{
final int n = Integer.MAX_VALUE;
int i = …Run Code Online (Sandbox Code Playgroud)