如何解决编写高效的代码并优化内存
| 我有这两个代码片段(用Java编写)哪个更有效?int foo(){
int result;
for(int i = 0; i < n;i++){
SomeObject a,b,c;
a = new SomeObject();
b = new SomeObject();
c = new SomeObject();
//do something with a,c
//and derive result
}
return result;
}
要么
int foo(){
int result;
SomeObject a,c;
a = new SomeObject();
b = new SomeObject();
c = new SomeObject();
for(int i = 0; i < n;i++){
a.flush(); //reset object do not create new though
b.flush(); //reset object do not create new though
c.flush(); //reset object do not create new though
//do something with a,c
//and derive result
}
return result;
}
在第二个片段中,我将局部变量移出了循环,因此有效地它仅创建了它们的一个实例。这有什么改善吗?
从逻辑上讲,当变量在循环内时,这将是有意义的。但是垃圾收集器会有效地清理对象吗?
编辑:更新了有关对象实例化的片段。
解决方法
您已将变量移出,但这些不是对象。假设您在循环的每次迭代中都将不同的值分配给
a
,ѭ3assign和c
,那么您根本没有减少内存分配-您只是不必要地扩大了变量的范围。
如果您不需要在循环中更改a
,b
和c
的值,那是另一回事了,最好在循环外而不是在每次迭代中分配它们。
最主要的是要了解对象和变量之间的区别。特别是,在循环的每次迭代中创建\“ new \”变量实际上并不会花费任何费用。
编辑:好的,对于更新的问题,显然在创建多少个对象方面存在差异。但是,确切地取决于第二种形式所发生的事情可能还是更可取的:它当然更容易理解,并且它并不依赖于flush
运算的细节。另一方面,如果创建ѭ9的实例非常昂贵(例如,它生成加密密钥),则针对此优化是一个好主意。
简而言之:这取决于。首先编写最易读的代码,对其进行度量,然后将其与性能要求进行比较。只有在有明显好处的情况下,才转向不太明显的代码。
, 按照书面规定,它们是相同的。在这两种情况下,一旦函数开始执行,SomeObject引用的内存就会在函数的堆栈帧中分配。
因此,请选择范围最有限的版本。这也将具有另一个优势-如果您的函数在循环后执行一个操作并执行了花费一些时间的操作,则在循环结束后SomeObject实例将有资格使用GC。
但是请注意,如果将一个或多个对象用ѭ10初始化,并且构造的对象在每次循环迭代中都相同且可重复使用,则会有实质性的区别。那么最好避免在每次循环迭代中不必要地创建和丢弃相同的对象。
编辑更新的问题
FWIW,在这个细节上我不同意Jon Skeet的观点:考虑到更新的问题,始终最好在循环外部构造对象并在每次迭代中重用它们。如果该方法中的其他代码过于复杂以至于使其不合需要,则需要重构的是方法而不是循环。
, 垃圾回收可以有效地清理对象,但这并不意味着成本为零。在第二个示例中,您必须考虑的是必须具有可变对象,这些可变对象可以将reset()返回到其原始状态,而该状态又不是零成本的。
大多数性能问题的答案是:尽可能清晰,简单地编写代码,结果通常也会具有良好的性能。如果确实有性能问题,请对应用程序进行概要分析,以查看可能需要更改的内容。
, 我已经实际测试过了,并且没有什么区别,因为编译器发现选项1可以更好地作为选项2进行处理,并将其更改为选项2。
首先为清楚起见编写代码,其次是效率(无论如何,编译器比您还聪明)
, 这取决于是否在两个实例中都通过每次循环迭代来构造它们,那么这两个效率都不高。如果在循环主体之外初始化它们,则后者会更快。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。