【问题标题】:Groovy for loop execution timeGroovy for 循环执行时间
【发布时间】:2009-05-28 12:33:51
【问题描述】:

O Groovy 大师,

这段代码 sn-p 运行大约 1 秒

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

而这个需要将近 9 秒

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

为什么会这样?

【问题讨论】:

    标签: groovy


    【解决方案1】:

    好的。这是我对原因的看法?

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

    1. ForInLoop 使用范围。迭代器用于在每个循环期间前进。比较 (
    2. ForLoop 使用传统的增量、检查条件并执行操作。对于检查条件 i ScriptBytecodeAdapter.compareLessThan。如果您深入研究该方法的代码,您会发现比较的双方都被视为对象,并且发生了很多事情,转换,将它们作为对象进行比较等等。

    ScriptBytecodeAdapter.compareLessThan --> ScriptBytecodeAdapter.compareTo --> DefaultTypeTransformation.compareTo

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

    我怀疑这是第二个循环需要更长的时间的原因。 再次,如果我错了或遗漏了什么,请纠正我......

    【讨论】:

    • 这几乎可以肯定地解释它。我知道 Java 风格的 for 循环在你可以做的事情上提供了更大的灵活性,但他们肯定可以对其最基本(也是最常用)的形式进行一些优化,以便它的性能与 for..in 循环一样好?对于从 Java 或 C# 过来的人来说,这是一个小的性能陷阱......
    • 没有人预料到这两个操作会出现如此大的差异。 groovy 可以改进的领域,特别是因为 Java 中的类似代码在 300 毫秒内执行。
    【解决方案2】:

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

    【讨论】:

      【解决方案3】:

      如果您可以按照 Jim 的建议从启动时消除潜在的伪影,那么我会冒险猜测 Groovy 中的 Java 样式 for 循环的实现不如原始 Groovy 样式的 for 循环那么好。它只是在用户请求后从 v1.5 开始添加的,所以它的实现可能是事后才想到的。

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

      我想知道您看到的差异是否与 Groovy 如何使用数字(基元)有关 - 因为它将所有基元包装在其等效的 Java 包装类(int -> Integer)中,我想这会减慢一些速度.我有兴趣了解使用包装类而不是整数循环 10,000,000 次的 Java 代码的性能。

      所以也许原始的 Groovy for 循环不会受到这种影响?不过,这只是我的猜测。

      【讨论】:

      • 小富,这些都是好点。我感到困惑的是底部循环应该是更快的循环,因为它只处理整数,而不是整数(尽管没有指定 j 的类型)。给定顺序,顶部循环应该更慢。
      猜你喜欢
      • 2014-07-27
      • 1970-01-01
      • 2016-04-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多