代码之家  ›  专栏  ›  技术社区  ›  jqno

int与long的迭代速度

  •  8
  • jqno  · 技术社区  · 15 年前

    我有以下两个程序:

    long startTime = System.currentTimeMillis();
    for (int i = 0; i < N; i++);
    long endTime = System.currentTimeMillis();
    System.out.println("Elapsed time: " + (endTime - startTime) + " msecs");
    

    long startTime = System.currentTimeMillis();
    for (long i = 0; i < N; i++);
    long endTime = System.currentTimeMillis();
    System.out.println("Elapsed time: " + (endTime - startTime) + " msecs");
    

    注意:唯一的区别是循环变量的类型( int long )

    当我运行此程序时,第一个程序始终在0到16毫秒之间打印,而不管 N . 第二个需要更长的时间。为了 N == Integer.MAX_VALUE ,在我的机器上运行大约1800毫秒。运行时间在 n .

    为什么会这样?

    我认为jit编译器优化了 int 死循环。有充分的理由,因为显然它什么也做不了。但为什么它不这样做 长的 也循环?

    一位同事认为我们可能正在测量jit编译器在 长的 循环,但是由于运行时间在 n ,情况可能不是这样。

    我正在使用JDK 1.6.0更新17:

    C:\>java -version
    java version "1.6.0_17"
    Java(TM) SE Runtime Environment (build 1.6.0_17-b04)
    Java HotSpot(TM) 64-Bit Server VM (build 14.3-b01, mixed mode)
    

    我使用的是Windows XP Professional x64版Service Pack 2,2.40GHz的Intel Core2四CPU。


    免责声明

    我知道微型市场在生产中没有用处。我也知道 System.currentTimeMillis() 并不像它的名字所说的那么准确。这只是我在闲逛时注意到的一件事,我只是好奇为什么会发生这种事;没别的了。

    4 回复  |  直到 15 年前
        1
  •  5
  •   Andrzej Doyle    15 年前

    这是一个有趣的问题,但老实说,我不相信在这里考虑热点的行为会产生有用的信息。你得到的任何答案在一般情况下都是不可转移的(因为我们正在研究hotspot在一种特定情况下的性能优化),所以它们将帮助你理解为什么一个no op比另一个更快, 但他们不会帮你写出更快的“真实”程序 .

    围绕这类事情编写非常容易误导的微观基准也非常容易-请看 this IBM DW article 对于一些常见的陷阱,如何避免它们和一些一般性的评论你在做什么。

    所以这确实是一个“无可奉告”的回答,但我认为这是唯一有效的回答。编译时琐碎的no op循环不 需要 为了更快,所以编译器在某些情况下没有被优化为更快。

        2
  •  4
  •   Community CDub    8 年前

    您可能正在使用32位jvm。对于64位的jvm,结果可能会有所不同。在32位jvm中,int可以映射到本机32位整数,并通过单个操作递增。同样的情况不会持续很长时间,这将需要更多的操作来增加。

    看到这个 question 关于内码和长码的讨论。

        3
  •  3
  •   Steve McLeod    15 年前

    我的猜测-这只是一个猜测-是不是:

    jvm的结论是第一个循环实际上什么也不做,所以它完全删除了它。for循环中没有变量“转义”。

    在第二种情况下,循环也不做任何事情。但是,确定循环不执行任何操作的jvm代码可能有一个“if(type of i)==int”子句。在这种情况下,删除do nothing for循环的优化只适用于int。

    删除代码的优化必须确保没有副作用。jvm代码编写者似乎是出于谨慎而犯了错误。

        4
  •  1
  •   Jesper    15 年前

    这样的微基准测试没有太多意义,因为结果在很大程度上依赖于hotspot jit的内部工作。

    另外,请注意您使用的系统时钟值 System.currentTimeMillis() 在所有操作系统上都没有1毫秒的分辨率。你不能用这个来精确地计时非常短的持续时间事件。

    看看这篇文章,这就解释了为什么Java中的微基准不是像大多数人想象的那么简单: Anatomy of a flawed microbenchmark