当前位置: 首页 > 面试题库 >

哪个循环具有更好的性能?为什么?

令狐弘益
2023-03-14
问题内容

String s = “”;
for(i=0;i<....){
s = some Assignment;
}

要么

for(i=0;i<..){
    String s = some Assignment;
}

我不需要在循环外再次使用“ s”。第一个选项可能更好,因为不会每次都初始化一个新的String。但是,第二个结果将导致变量的范围仅限于循环本身。

编辑:回应米尔豪斯的回答。在循环中将String分配给常量是没有意义的吗?不,这里的“某些分配”是指从要迭代的列表中获得的变化值。

另外,问题不是因为我担心内存管理。只想知道哪个更好。


问题答案:

范围最好

使用第二个选项:

for ( ... ) {
  String s = ...;
}

范围不影响性能

如果您使用JDK的javap工具反汇编每个编译器的代码,则在两种情况下,您都将看到循环编译为完全相同的JVM指令。还要注意,Brian R.Bondy“选项3”与选项1相同。使用更紧密的示波器时,不会在堆栈中添加或删除任何多余的东西,并且两种情况下在堆栈上都使用相同的数据。

避免过早初始化

两种情况之间的唯一区别是,在第一个示例中,变量s被不必要地初始化。这是与变量声明的位置不同的问题。这会增加两条浪费的指令(以加载字符串常量并将其存储在堆栈帧插槽中)。一个好的静态分析工具会警告您,您永远不会读取分配给它的值s,而好的JIT编译器可能会在运行时忽略它。

您可以简单地通过使用空声明(即String s;)来解决此问题,但这被认为是不好的做法,并且还会在下面讨论另外一个副作用。

通常,将伪造的值(如like
null)分配给变量只是为了掩盖编译器错误,该错误是在未初始化变量的情况下读取变量的。该错误可以作为变量范围太大的暗示,并且在需要接收有效值之前先声明了该错误。空声明迫使您考虑每个代码路径;请勿通过分配虚假值来忽略此有价值的警告。

节省堆叠插槽

如前所述,尽管两种情况下的JVMhtml" target="_blank">指令都相同,但是有一个细微的副作用,使它在JVM级别上最好使用尽可能有限的范围。这在该方法的“局部变量表”中可见。考虑一下如果您有多个循环,并且在不必要的大范围内声明了变量,会发生什么情况:

void x(String[] strings, Integer[] integers) {
  String s;
  for (int i = 0; i < strings.length; ++i) {
    s = strings[0];
    ...
  }
  Integer n;
  for (int i = 0; i < integers.length; ++i) {
    n = integers[i];
    ...
  }
}

变量sn可以在它们各自的循环中声明,但是由于它们不是,因此编译器在堆栈帧中使用两个“槽”。如果在循环内声明它们,则编译器可以重用同一插槽,从而使堆栈帧更小。

真正重要的是

但是,这些问题大多数都不重要。一个好的JIT编译器将看到不可能读取您浪费分配的初始值,并且无法优化分配。在此处保存插槽,否则将无法建立或破坏您的应用程序。

重要的是使代码易于阅读且易于维护,在这方面,使用有限的范围显然更好。变量的范围越小,就越容易理解其用法以及对代码进行的更改将产生何种影响。



 类似资料:
  • 问题内容: 考虑以下两行代码 和 在性能上,以上两个语句有什么区别吗?我见过很多人使用后者,当被问及他们说这是最佳实践时,没有充分的理由。 问题答案: 没有不同。 第二个原因仅仅是因为C / C ++程序员总是执行分配而不是比较。 例如 而java编译器会生成编译错误。 因此,由于可读性强,我个人更喜欢第一个,人们倾向于从左到右阅读,而不是。

  • 问题内容: 我正在优化我的大型应用程序。我对以下两种方法感到困惑,请帮助确定哪种方法更快。 内联样式属性 使用ng样式 使用一次样式 注意 :对于,我使用了AngularOnce指令。 提前致谢。请告诉我哪个更快,为什么。 问题答案: 由于您正在优化相当大的应用程序,因此性能肯定受到质疑,我认为性能会更好,因为它可以在模型上设置监视,并且仅当模型更改时才会更新视图。 因此,我会选择还是根据您的情况

  • 问题内容: 有时我们可以同时使用派生表和临时表编写查询。我的问题是哪个更好?为什么? 问题答案: 派生表是一种逻辑构造。 可以将其存储在中,在运行时通过在每次访问时重新评估基础语句来构建,甚至可以对其进行优化。 临时表是一种物理构造。它是在其中创建的表,并在其中填充了值。 哪种更好取决于查询所使用的查询,用于派生表的语句以及许多其他因素。 例如,每次使用时都可以(并且很可能会)重新评估in中的(公

  • 问题内容: 我在评估我的Java代码时遇到了一个大问题。为了简化问题,我编写了以下代码,它们产生相同的奇怪行为。重要的是方法run()和给定的双倍价值率。对于运行时测试(在main方法中),我将速率设置为0.5倍,另一次设置为1.0。如果值为1.0,则将在每次循环迭代中执行if语句;如果值为0.5,则将执行一半的if语句。因此,在第一种情况下,我希望运行时更长,但事实恰恰相反。谁能解释这个现象?

  • 问题内容: 为了观看对象作用域变量,将其设置为true还是更好? 对于一个对象变量(如15点的属性,一些嵌套2级深)与输入元件和更新在视图中,有多差与设定为?这是要避免的大事吗? 是一个更好的解决方案? 我正在寻找轻松的方式来提高AngularJS应用程序的性能(我仍然停留在v1.2.2上)。 问题答案: 该功能是上述两种配置之间的中间地带。它比普通的$ watch()函数更深入;但是,它几乎不像