简体   繁体   English

java for 循环性能差异

[英]java for loop performance difference

I am running below simple program, I know this is not best way to measure performance but the results are surprising to me, hence wanted to post question here.我在简单的程序下运行,我知道这不是衡量性能的最佳方法,但结果令我惊讶,因此想在这里发布问题。

public class findFirstTest {

    public static void main(String[] args) {

        for(int q=0;q<10;q++) {
            long start2 = System.currentTimeMillis();
            int k = 0;
            for (int j = 0; j < 5000000; j++) {
                if (j > 4500000) {
                    k = j;
                    break;
                }
            }
            System.out.println("for value  " + k + " with time " + (System.currentTimeMillis() - start2));
        }
    }
}

results are like below after multiple times running code.多次运行代码后的结果如下所示。

for value  4500001 with time 3
for value  4500001 with time 25 ( surprised as it took 25 ms in 2nd iteration)
for value  4500001 with time 0
for value  4500001 with time 0
for value  4500001 with time 0
for value  4500001 with time 0
for value  4500001 with time 0
for value  4500001 with time 0
for value  4500001 with time 0
for value  4500001 with time 0

so I am not understanding why 2nd iteration took 25ms but 1st 3ms and later 0 ms and also why always for 2nd iteration when I am running code.所以我不明白为什么第二次迭代需要 25 毫秒但第一次 3 毫秒和后来的 0 毫秒,以及为什么在我运行代码时总是进行第二次迭代。

if I move start and endtime printing outside of outer forloop then results I am having is like如果我将开始和结束时间打印移到外部 forloop 之外,那么我得到的结果就像

for value  4500001 with time 10

In first iteration, the code is running interpreted.在第一次迭代中,代码运行解释。

In second iteration, JIT kicks in, slowing it down a bit while it compiles to native code.在第二次迭代中,JIT 开始发挥作用,在编译为本机代码时会稍微减慢它的速度。

In remaining iterations, native code runs very fast.在剩余的迭代中,本机代码运行得非常快。

Because your winamp needed to decode another few frames of your mp3 to queue it into the sound output buffers.因为您的 winamp 需要解码 mp3 的另外几帧以将其排队到声音 output 缓冲区中。 Or because the phase of the moon changed a bit and your dynamic background needed changing, or because someone in east Croydon farted and your computer is subscribed to the 'smells from London' twitter feed.或者因为月相发生了一点变化,你的动态背景需要改变,或者因为东克罗伊登的某个人放了屁,而你的电脑订阅了“来自伦敦的气味”twitter 提要。 Who knows?谁知道?

This isn't how you performance test.这不是您进行性能测试的方式。 Your CPU is not such a simple machine after all;你的 CPU 毕竟不是这么简单的机器; it has many cores, and each core has pipelines and multiple hierarchies of caches.它有很多核心,每个核心都有管道和多层缓存。 Any given core can only interact with one of its caches, and because of this, if a core runs an instruction that operates on memory which is not currently in cache, then the core will shut down for a while: It sends to the memory controller a request to load the page of memory with the memory you need to access into a given cachepage, and will then wait until it is there;任何给定的内核只能与它的一个缓存交互,因此,如果一个内核运行一条指令,该指令在当前不在缓存中的 memory 上运行,那么该内核将关闭一段时间:它发送到 memory Z594C18ABAZ05F2C6E0E04Dmemory请求加载 memory 的页面和 memory 您需要访问给定的缓存页面,然后等待它在那里; this can take many, many cycles.这可能需要很多很多周期。

On the other end you have an OS that is juggling hundreds of thousands of processes and threads, many of them internal to the kernel, per-empting like there is no tomorrow, and trying to give extra precedence to processes that are time sensitive, such as the aforementioned winamp which must get a chance to decode some more mp3 frames before the sound buffer is fully exhausted, or you'd notice skipping.另一方面,您有一个操作系统,它正在处理数十万个进程和线程,其中许多是 kernel 内部的,就像没有明天一样,并且试图为时间敏感的进程提供额外的优先级,例如正如前面提到的 winamp必须有机会在声音缓冲区完全耗尽之前解码更多的 mp3 帧,否则您会注意到跳过。 This is non-trivial: On ye olde windows you just couldn't get this done which is why ye olde winamp was a magical marvel of engineering, more or less hacking into windows to ensure it got the priority it needed.这是不平凡的:在您的 windows 上,您无法完成此操作,这就是为什么您的 winamp 是工程的神奇奇迹,或多或少地侵入 windows 以确保它获得所需的优先级。 Those days are long gone, but if you remember them, well, draw the conclusion that this isn't trivial, and thus, OSes do pre-empt with prejudice all the time these days.那些日子已经一去不复返了,但是如果你还记得它们,那么,得出的结论是,这不是微不足道的,因此,这些天操作系统确实总是带着偏见先发制人。

A third significant factor is the JVM itself which is doing all sorts of borderline voodoo magic, as it has both a hotspot engine (which is doing bookkeeping on your code so that it can eventually conclude that it is worth spending considerable CPU resources to analyse the heck out of a method to rewrite it in optimized machinecode because that method seems to be taking a lot of CPU time), and a garbage collector.第三个重要因素是 JVM 本身正在做各种边缘巫术魔术,因为它有一个热点引擎(它正在对您的代码进行簿记,以便它最终可以得出结论,值得花费大量 CPU 资源来分析有一种方法可以用优化的机器代码重写它,因为该方法似乎需要大量的 CPU 时间)和一个垃圾收集器。

The solution is to forget entirely about trying to measure time using such mere banalities as measuring currentTimeMillis or nanoTime and writing a few loops.解决方案是完全忘记尝试使用诸如测量 currentTimeMillis 或 nanoTime 之类的陈词滥调来测量时间并编写一些循环。 It's just way too complicated for that to actually work.这太复杂了,无法实际工作。

No. Use JMH .不,使用JMH

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM