临时对象对软件性能的影响
第五阅读网 FiveRead.com 2001年05月18日 Yesky
临时对象的存在时间一般都比较短暂,除了作为其他数据的容器外,没有其他什么用途,开发人员一般用它向方法传递数据或从方法中返回数据。文章的第一部分探讨了创建临时对象是如何影响程序性能的,并表明恰当的类的接口设计可以有效地减少临时对象的创建。通过避免设计这样的接口,就可以减少临时对象的创建,降低对程序性能的影响程度。在本篇文章中,我将讨论过多地创建临时对象的问题并在后面的文章中提供一些成熟的技术来避免过多地创建临时对象。
仅仅对String说NO?
说到创建临时对象,String类是最大的"罪魁祸手"。为了说明这一点,我在这篇文章的第一部分中开发了一个表达式匹配类的例子,并演示了一个看起来颇为正常的接口是如何因为创建了临时对象而比一个具有较好接口的类似的类运行速度慢数倍的。下面是最初的和性能较好的类的接口:
BadRegExpMatcher
public class BadRegExpMatcher {
public BadRegExpMatcher(String regExp);
/** 把输入文本与特定的表达式进行匹配,如果匹配则返回匹配的文本,否则返回空字符 */
public String match(String inputText);
}
BetterRegExpMatcher
class BetterRegExpMatcher {
public BetterRegExpMatcher(...);
/** 向匹配子程序提供多种格式的输入━━String、字符数组和字符数组的子集。如果不匹配则返回-1,如果匹配,则返回匹配开始处的偏移量 */
public int match(String inputText);
public int match(char[] inputText);
public int match(char[] inputText, int offset, int length);
/** 如果匹配,则返回匹配的长度,调用程序可以从返回的匹配开始处偏移量和长度重新构造匹配的文本 */
public int getMatchLength();
/** 如果调用程序需要,这个例程可以很方便地构造出匹配字符串 */
public String getMatchText();
}
大量使用BadRegExpMatcher的程序要比使用BetterRegExpMatcher的程序运行速度慢一些。第一,调用程序必须创建String对象向match()传递参数,match()也必须创建一个String对象向调用程序返回匹配的文本。每次调用时都会创建二个对象,这听起来也许没有什么大问题,但如果频繁地调用match(),创建这二个对象对性能产生的影响就大了。使用BadRegExpMatcher的程序的性能问题并不源于其编码而源于其接口,象这样设计的接口,临时对象的创建是不可避免的。
BetterRegExpMatcher用比较简单的数据类型(整型、字符数组)取代了在match()中使用的String对象,从而无需在调用程序和match()之间通过中间对象传递数据。
由于在设计阶段比在完成整个程序后再进行修改能够更好地避免程序性能方面的问题,因此应该在类的接口如何处理对象的创建这个问题上多花些时间。在RegExpMatcher中,其方法要求输入和返回String对象就可能对性能有潜在的影响,因为String类的对象是不可变的,因此对String类对象参数进行处理就会要求在每次调用时创建一个新的String对象。
由于不可变性通常与额外的对象创建联系在一起━━这大部分原因都要"归功"于其不可变性,许多编程人员就断定不可变的对象一定会影响程序的性能。其实真实的情况要复杂得多,实际上,不可变性有时还能够提升程序的性能,可变的对象也能够引起程序性能的下降,可变性对程序性能的影响取决于其使用方式。
程序会经常对文本字符串进行操作和修改━━不可改变性确实是一个麻烦。在每次对String进行操作时━━例如查找或选择一个前缀或子串,把它转换为大写或小写,或者将二个字符串合并成一个新的字符串时,就必须创建一个新的String类对象。
另一方面,我们可以自由地共享一个不可变对象的地址而无需担心对象会被改变,此时,不可变对象在性能上就比可变对象要好许多。
上一篇:优化软件性能的方法
下一篇:数据类型对软件性能的影响













文章评论
发表您的评论 查看完整内容