Groovy for循环执行时间

时间:2009-05-28 12:33:51

标签: groovy

O Groovy Gurus,

此代码段大约运行1秒

    for (int i in (1..10000000)) {
         j = i;
    }

虽然这个花了将近9秒

    for (int i = 1; i < 10000000; i++) {
         j = i;
    }

为什么会这样?

3 个答案:

答案 0 :(得分:9)

确定。这是我对为什么的看法?

如果将两个脚本转换为字节码,您会注意到

  1. ForInLoop使用Range。迭代器用于在每个循环期间前进。比较(&lt;)直接用于int(或整数)以确定是否满足退出条件
  2. ForLoop使用传统增量,检查条件并执行操作。为了检查条件i&lt; 10000000它使用Groovy的ScriptBytecodeAdapter。compareLessThan。如果你深入研究该方法的代码,你会发现比较的两个方面都被视为对象,并且有很多事情正在进行,转换,将它们作为对象进行比较等。
  3. ScriptBytecodeAdapter .compareLessThan - &gt; ScriptBytecodeAdapter。compareTo - &gt; DefaultTypeTransformation。的compareTo

    typehandling包中有其他类专门为数学数据类型实现compareTo方法,不确定为什么它们没有被使用(如果它们没有被使用)

    我怀疑这是第二个循环花费更长时间的原因。 如果我错了或遗失了某些内容,请再次纠正我......

答案 1 :(得分:2)

在测试中,确保在采取措施之前“加热”JVM,否则您最终可能会触发平台中的各种启动操作(类加载,JIT编译)。连续多次运行测试。此外,如果您在进行垃圾收集时进行了第二次测试,则可能会产生影响。尝试运行每次测试100次并在每次测试后打印出时间,看看它告诉你什么。

答案 2 :(得分:1)

如果你可以像Jim建议的那样从启动时消除潜在的工件,那么我就会猜测Groovy中的Java风格for循环与原始的Groovy风格for循环没有那么好实现。它只是在用户请求之后从v1.5开始添加,因此它的实现可能是一个事后的想法。

您是否看过为两个示例生成的字节码,看看是否有任何差异?有一个关于Groovy性能here的讨论,其中一条评论(来自一个'johnchase')说:

  

我想知道你看到的差异是否与Groovy如何使用数字(原语)有关 - 因为它将所有原语包装在它们等效的Java包装器类中(int - &gt; Integer),我想这样会使事情变慢位。我有兴趣看到使用包装类而不是整数来循环10,000,000的Java代码的性能。

那么也许最初的Groovy for循环不会受此影响?我真的只是在猜测。