【问题标题】:Is there a performance issue using a temporary variable?使用临时变量是否存在性能问题?
【发布时间】:2013-07-17 22:50:19
【问题描述】:

我有一个关于在 java 中创建新对象的问题。

假设我有方法叫:foo(String[] a)

我想将一个新的String[] 传递给foo,这只是一种用途,更适合

性能 1 或 2

1.

String[] a = new String[]{"a"};

foo(a);

2.

foo(new String[]{"a"});

感谢您的帮助

【问题讨论】:

  • 它的 1 行代码与 performance 无关。
  • @Junaid 好吧,doSomethingReallySlow() 只是“一行”:D
  • @user2246674 - 是的。但是关于这个问题有nothingAffectingPerformance():D
  • 使用javap -c Class.class检查生成的字节码,其中包含对foo的调用,使用这两种方法,使用你最喜欢的分析器测量它们,对此进行重压测试,只是要注意任何这些都没有性能增益或损失
  • 大多数时候代码的可读性比性能的轻微提升更重要。这看起来像是premature optimization 的经典示例。

标签: java performance


【解决方案1】:

你可以检查字节码:

1.

  public static void main(java.lang.String[]);
    Code:
       0: iconst_0      
       1: anewarray     #2                  // class java/lang/String
       4: astore_1      
       5: aload_1       
       6: invokestatic  #3                  // Method foo:([Ljava/lang/String;)V
       9: return 

2.

  public static void main(java.lang.String[]);
    Code:
       0: iconst_0      
       1: anewarray     #2                  // class java/lang/String
       4: invokestatic  #3                  // Method foo:([Ljava/lang/String;)V
       7: return  

唯一的区别是,在 (2) 中,没有存储引用 (astore_1),也不需要加载任何引用 (aload_1)。这几乎肯定不会导致性能差异(无论如何您都不应该担心这种微小的优化),但如果您不打算在程序中再次引用a(如你在your comment 中提到)并且不存在可读性侵权。

我认为可读性组件非常重要:我宁愿创建一个变量来存储数组(即使我永远不会多次引用这个变量)而不是拥有一个超长、不可读的行。当然,在您的示例中,可读性没有问题,但是当出现更复杂的情况时需要考虑。

【讨论】:

  • 查看字节码不会给你一个有意义的答案。实际性能取决于 JIT 编译器如何将这些字节码转换为本机代码。不同的字节码并不意味着不同的本机代码。 (相同的字节码也不意味着相同的本机代码......)
  • @StephenC 在这种特殊情况下,我相信查看字节码会发现第一个变体永远不会被 JIT 化为优于第二个变体的东西,而第二个变体 可能 跑赢第一。显然,正如我在答案中详述的那样,这里的性能差异可能可以忽略不计。
  • 这是一个似是而非的理论(在这种情况下可能是正确的),但它不是基于事实的。 JIT 是一个黑盒子。它没有指定优化什么或如何优化。如果您想知道真正发生了什么,您需要检查 JIT 编译器源代码或本机代码,而不是输入字节码。
【解决方案2】:

如果您使用临时局部变量来存储经常使用的、计算成本高的值,可以提高性能。对于一次性值,它们仍然可以为命名一个值并明确其意图提供很大帮助 - 这样做的性能成本绝对可以忽略不计。

拥有或没有用于存储一次性值的变量与性能无关,请将您的精力集中在分析器突出显示为瓶颈的代码部分,并且不要将您的时间浪费在这些无关紧要的事情上微优化。而且更重要的是编写易于理解的代码,记住……“过早的优化是万恶之源。”

【讨论】:

【解决方案3】:

我认为不可能以一般的方式明确地回答这个问题。甚至 arshajii 显示 IL 的响应也是有限的。

在您的代码中,JIT 编译器无论如何都会优化它。

优化级别很大程度上取决于版本、平台、实施和一百万个其他变量。

...现在,如果您在两者之间有一个阅读围栏,那么抖动无法优化它们,那么您将拥有不同的故事。

【讨论】:

  • 我很感兴趣,您有没有说明 JIT 会对此进行优化的参考资料?
  • @selig - AFAIK,不存在这样的参考......除了 JIT 编译器源代码本身。但是,可以合理地假设 JIT 编译器将执行 明显、简单 优化......像这样。 (您也可以通过转储和检查本机代码来确认这一点......)
  • @selig - 我会问另一个问题。这种优化是如此基本,我需要文档来证明它没有被制作。 :-)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-06-25
  • 2017-09-07
  • 1970-01-01
  • 2012-02-14
  • 2011-09-07
相关资源
最近更新 更多