Nic*_*ole 0 java performance encapsulation
鉴于以下两个代码选项,第二个代码选项是否有任何性能优势(超过大规模或长时间)?
选项1
private Map<Long, Animal> animals = ...;
public Map<Long, Animal> getAnimals() {
return animals;
}
public void useAnimals() {
for (int i=0; i < SOME_LARGE_NUMBER; i++) {
Animal animal = getAnimals().get(id);
}
// Many many calls to getAnimals() are made...
}
Run Code Online (Sandbox Code Playgroud)
选项2 - 没有吸气剂
private Map<Long, Animal> animals = ...;
public void useAnimals() {
for (int i=0; i < SOME_NUMBER; i++) {
Animal animal = animals.get(id);
}
// No method calls made
}
Run Code Online (Sandbox Code Playgroud)
如果它对性能有害,为什么,以及我该如何确定它是否值得减轻?
并且,将存储结果getAnimals()作为本地提供一个好处...
SOME_NUMBER是数百或数千?SOME_NUMBER只是10的数量级?注意:我之前说过"封装".我将其更改为"getter",因为其目的实际上不是该字段无法修改,而是无法重新分配.封装只是为了从子类中删除赋值的责任.
很可能JVM会getAnimals()在紧密循环中内联调用,有效地回退到选项1.所以不要打扰,这实际上是微观(纳米?)优化.
另一件事是从字段访问迁移到本地变量.这听起来不错,因为this每次总是在堆栈上有一个引用(两次内存访问与一次)时,不是遍历引用.但是我相信(如果我错了,请纠正我),因为它animals是私有的,而且非volatileJVM将在运行时为您执行此优化.
第二个片段比第一个片段更封装.第一个允许访问任何人的内部映射,而第二个将它封装在类中.
两者都将带来可比的表现.
编辑:既然你改变了问题,我也会改变答案.
如果你通过一个getter,并且getter不是final,这意味着子类可能会返回另一个映射,而不是你在类中保存的映射.选择是否希望您的方法在子类的地图上或在类的地图上操作.两者都可以接受,具体取决于具体情况.
无论如何,假设您的子类总是制作地图的防御性副本,如果不将getter的结果缓存在局部变量中,则最终会有很多副本useAnimals.可能需要始终处理子类映射的最新值,但我怀疑是这种情况.
如果没有子类,或者子类没有覆盖该方法,或者通过始终返回相同的映射来覆盖它,则两者都将导致可比较的性能,您不应该关心它.
| 归档时间: |
|
| 查看次数: |
596 次 |
| 最近记录: |