Java 可读性与性能
最近,我们在工作中讨论了局部变量对Java代码的性能和可读性的影响。我的一些同事反对这样的声明Java 可读性与性能,java,performance,code-readability,Java,Performance,Code Readability,最近,我们在工作中讨论了局部变量对Java代码的性能和可读性的影响。我的一些同事反对这样的声明 new DoSomethingCmd(new SelectionContext(context, keys), infoStuff.getCurrentRole().getRole_id()).execute(getResultContainer()); 将大大提高应用程序的性能。他们愿意为此牺牲代码的可读性。他们这样说对吗?上述版本的性能是否比(比如)本版本明显更高 final Selection
new DoSomethingCmd(new SelectionContext(context, keys), infoStuff.getCurrentRole().getRole_id()).execute(getResultContainer());
将大大提高应用程序的性能。他们愿意为此牺牲代码的可读性。他们这样说对吗?上述版本的性能是否比(比如)本版本明显更高
final SelectionContext selectionContext = new SelectionContext(context, keys);
final String roleId = infoStuff.getCurrentRole().getRole_id();
final DeleteSomethingCmd deleteSomethingCmd = new DeleteSomethingCmd(selectionContext,roleId);
deleteSomethingCmd.execute(getResultContainer());
我意识到第一条语句本身并不难理解,但当您的大多数代码都是这样构造的时候,复杂性会迅速增加
谢谢你的意见
他们这样说对吗
不,他们不是。将某些内容存储在局部变量中并随后从中读取的成本接近于0,就这么简单——这绝对不是你应该花时间优化的事情,甚至不应该为此而担心。不要将所有内容放在一行高度复杂的行中,从而牺牲可读性。第一个版本的性能并不比第二个版本好多少。我怀疑您能否可靠地衡量性能差异。此外,在jit优化之后,结果机器代码应该是相同的。优化版本唯一的好处是堆栈中的变量少了一些,从而略微增加了内存消耗。性能应该仔细衡量(谷歌如何对一个问题进行基准测试),但我严重怀疑它是否有任何明显的效果 此外,花时间在一段不经常使用的代码中提高性能只会浪费开发人员的时间,这是非常昂贵的 在这种情况下,可读性应该占上风 编辑:无论如何,如果你使用适当的缩进,我不认为这两个版本在可读性方面有太大的不同:
new DoSomethingCmd(
new SelectionContext(context, keys),
infoStuff.getCurrentRole().getRole_id()
).execute(getResultContainer());
此文本的优点是,您没有不再需要的已定义变量(selectionContext
,roleId
)(因此,当您再次阅读该方法时,它们不会与更多“持久”变量混合)。无论如何,这是可以解释的;底线是,你不应该担心优化,除非你有这样做的动机
除此之外,Java编程还有一些指导原则,它们为您提供了真正有用的技巧,可以真正帮助您(例如,使用
StringBuilder
连接字符串)。一个人的时间比一台计算机的时间贵数百万倍
<>如果代码行被执行的次数比程序员要看的要多百万倍,那么<强> > <>强>你应该考虑优化。但在那之前肯定不会
即使如此,如果编译器是愚蠢的,那么进行优化也是毫无意义的
别忘了 严格地说,这两个例子之间没有可测量的差异(无论如何,在现代系统上没有)。但是,通过编写大量较低级别的代码来完成可以在较高级别使用较少代码完成的任务,确实可以大大提高性能。例如,在许多情况下,使用阵列比使用任何集合API都要快(可能不多,但确实如此)。但这样做不仅会降低可读性,还会降低可维护性,而且通常会导致性能的显著提高
代码应始终组织良好且可读。只有在获得良好的性能指标后,才应该考虑放弃这些指标以提高性能。我在这里看到了几个函数调用
- 两次调用
new
- 一个
构造函数SelectionContext
- 调用
getRole\u id()
- 一个
构造函数DeleteSomethingCmd
- 调用
GetResultContainer()
- 调用
deleteSomethingCmd
透视就是一切。如果我理解了右上角的代码,那么您的同事似乎认为创建引用变量比创建匿名变量要慢。是这样吗?他们为什么这么认为?我很高兴把这些优化留给内置的优化器。他们很擅长这个。最好是我们所看到的源代码易于理解。除非您进行了其他度量,否则您应该为清晰和简单而编写代码。这通常也足够快。当你衡量一个性能问题时,只考虑替代。性能优化通常没有帮助,只是增加了复杂性。由于堆栈空间是预先分配的,我不会认为堆栈上的某些变量会增加内存消耗。在需要额外的内存块之前,您需要数千个额外的变量。我的回答中的一个问题是,它假设一个“哑”编译器为每个变量提供固定的、不同的位置。经过优化的编译器可能会发现不再使用
roleId
,并重用其内存位置,例如,deleteSomethingCmd
,从而减少这一小好处。同样,应该使用基准测试来检查优化,以验证实际的改进。好的,javac
可能会在堆栈帧中为它们保留插槽,但这些插槽只是JVM预先分配的堆栈中的几个字节,大小为几百kB。表示“从JavaSE6开始,该值在32位VM中为320k,在64位VM中为1024k。”并且“64k是堆栈sp的最小数量