Java:空循环使用多长时间? [英] Java: how much time does an empty loop use?

查看:144
本文介绍了Java:空循环使用多长时间?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图在Java中测试自动装箱和拆箱的速度,但是当我尝试将它与原语上的空循环进行比较时,我注意到了一个奇怪的事情。这个片段:

I am trying to test the speed of autoboxing and unboxing in Java, but when I try to compare it against an empty loop on a primitive, I noticed one curious thing. This snippet:

for (int j = 0; j < 10; j++) {
    long t = System.currentTimeMillis();
    for (int i = 0; i < 10000000; i++)
        ;
    t = System.currentTimeMillis() - t;
    System.out.print(t + " ");
}

每次运行时,都会返回相同的结果:

Every time I run this, it returns the same result:

6 7 0 0 0 0 0 0 0 0

为什么前两个循环总是需要一些时间,其余的似乎被系统跳过了吗?

Why does the first two loops always take some time, then the rest just seem to be skipped by the system?

在这篇文章的答案中,据说即时汇编将能够优化这一点。但是,如果是这样,为什么前两个循环仍然需要一些时间?

In this answer to this post, it is said that Just-In-Time compilation will be able to optimize this away. But if so, why the first two loops still took some time?

推荐答案

JIT在执行某段代码后触发多次。

JIT triggers AFTER a certain piece of code has been executed many times.

HotSpot JVM将尝试识别代码中的热点。热点是您的代码片段,可以执行很多次。为此,JVM将计算各种指令的执行,并且当它确定经常执行某个部分时,它将触发JIT。 (这是一个近似值,但很容易理解这种方式解释)。

The HotSpot JVM will try to identify "hot spots" in your code. Hot spots are pieces of your code that are executed many many times. To do this, the JVM will "count" the executions of various instructions, and when it determines a certain piece is executed frequently, it will trigger the JIT. (this is an approximation, but it's easy to understand explained this way).

JIT(即时)获取该段代码,并尝试制作它更快。

The JIT (Just-In-Time) takes that piece of code, and tries to make it faster.

JIT使你的代码运行得更快的技术很多,但最常引起混淆的是:

The techniques used by the JIT to make your code run faster are a lot, but the one that most commonly creates confusion are :


  1. 它将尝试确定该段代码是否使用其他地方未使用的变量(无用变量),并将其删除。

  2. 如果您多次获取并释放相同的锁(例如调用同一对象的同步方法),它可以获取锁一次并在单个同步块中执行所有调用

  3. 如果您访问未声明为volatile的对象的成员,它可以决定对其进行优化(将值放在寄存器中等等),在多线程代码中创建奇怪的结果。

  4. 它将内联方法,以避免调用的成本。

  5. 它会将字节码转换为机器码。

  6. 如果循环完全没用,可以完全删除。

  1. It will try to determine if that piece of code uses variables that are not used anywhere else (useless variables), and remove them.
  2. If you acquire and release the same lock multiple times (like calling synchronized methods of the same object), it can acquire the lock once and do all the calls in a single synchronized block
  3. If you access members of an object that are not declare volatile, it can decide to optimize it (placing values in registers and similar), creating strange results in multi-threading code.
  4. It will inline methods, to avoid the cost of the call.
  5. It will translate bytecode to machine code.
  6. If the loop is completely useless, it could be completely removed.

所以,对你的问题的正确答案是,在JIT之后,一个空循环没有时间执行..很可能不再存在了。

So, the proper answer to your question is that an empty loop, after being JITed, takes no time to execute .. most probably is not there anymore.

再次,那里还有很多其他的优化,但根据我的经验,这些都是最令人头疼的问题。

Again, there are many other optimizations, but in my experience these are among those that have created most headaches.

此外,JIT正在改进任何新版本的Java,有时它甚至根据平台有所不同(因为它在某种程度上是特定于平台的)。 JIT完成的优化很难理解,因为你通常无法使用javap和检查字节码找到它们,即使在最新版本的Java中,其中一些优化已经直接转移到编译器(例如,因为Java 6编译器是能够检测并警告未使用的局部变量和私有方法。)

Moreover, JIT is being improved in any new version of Java, and sometimes it is even a bit different depending on the platform (since it is to some extent platform specific). Optimizations done by the JIT are difficult to understand, because you cannot usually find them using javap and inspecting bytecode, even if in recent versions of Java some of these optimizations have been moved to the compiler directly (for example, since Java 6 the compiler is able to detect and warn about unused local variables and private methods).

如果你正在编写一些循环来测试某些东西,通常最好将循环放在一个方法,在计时之前调用该方法几次,给它一个加速轮,然后执行定时循环。

If you are writing some loops to test something, it is usually good practice to have the loop inside a method, call the method a few times BEFORE timing it, to give it a "speed up" round, and then perform the timed loop.

这通常会在像你这样的简单程序中触发JIT,即使不能保证它会实际触发(或者它甚至存在于某个平台上)。

This usually triggers the JIT in a simple program like yours, even if there is no guarantee that it will actually trigger (or that it even exists on a certain platform).

如果你想得到关于JIT或非JIT时间的偏执(我做过):做第一轮,计时循环的每次执行,并等到时间稳定(例如,与平均值的差异小于10%),然后从你的真实时间开始。

If you want to get paranoid about JIT or non JIT timing (I did): make a first round, timing each execution of the loop, and wait until the timing stabilize (for example, difference from the average less than 10%), then start with your "real" timing.

这篇关于Java:空循环使用多长时间?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆