使用null值而不是默认值是否会提高性能?

3
他们说过度优化是万恶之源,但是这里还是要谈一下...
我们有一个高性能的应用程序;在服务器端由Java支持的内存缓存和需要非常迅速的C# GUI在客户端。
我注意到目前我们在缓存中使用的对象具有默认值-例如将字符串默认初始化为"",将日期初始化为1/1/1999而不是将它们保留为空。
现在我可能会很挑剔,但这是否会给每个对象增加一点点空间(无论是在缓存中还是在对象被序列化时)而不是如果它为空呢?
只是想知道当我们的对象数量开始变得相当大时,会获得什么样的改进(如果有的话)...
谢谢, 戴夫。

6
@f1dave:哇...高性能应用程序,你居然还在对象中存储日期?时间点应该存储在原始数据类型中(比如Java中的long),作为自纪元以来经过的(毫)秒数。这几乎总是正确的,特别是如果性能是一个问题时。唯一需要将那个时间点“格式化”为日期的时刻是当某个用户想要以用户友好的方式阅读它(比如按照自己所在的时区等)。 - SyntaxT3rr0r
@Anon。我不明白那与性能问题有任何关系。 - Kaj
@Kaj - OP 询问的是“更多一点空间”,而不是 CPU。 - Anon
而使用默认值(也称为“null对象模式”)通常是为了防止NPE。 - Anon
哦,看起来我肯定会担心NPE。但是我现在戴上了我的黑帽子(愚蠢的帽子,无论如何)。@SyntaxT3rr0r - 缓存存储对象。这些对象本身具有尽可能基本的属性,大多数是原始类型。但是它们确实使用java.util.Date。 - f1dave
显示剩余3条评论
1个回答

3
过早的优化确实是有害的。
但是,如果性能是应用程序的关键要求,考虑应用程序的性能特征并采用适当的设计策略进行性能优化是完全合理的 :-)
以下是一些相关要点:
- 相对于默认值,使用 null 会带来一些(轻微的)性能优势。原生代码检查 null 值比解引用对象引用并检查该对象的值更容易。如果这在高性能应用程序中导致缓存未命中,那么可能会变得痛苦。 - 存在一些额外的内存开销,但这可能并不重要——假设您多次重复使用相同的默认值对象(即许多键指向相同的值),那么总体上不会有太多额外的对象实例。 - 如果您的默认值是不可变的单例对象,则有三个原因会极大地帮助: - 您只需要一个不可变对象的副本,而不是 "" 的不同实例(String.intern() 在此处有所帮助!) - 多次使用单个对象更有可能被高效地缓存 - 您可以使用引用相等性(value == DEFAULT_SINGLETON)来测试默认值,从而避免在 DEFAULT_SINGLETON 是静态 final 值时需要进行指针解引用的需要。 - 如果您确实使用不可变单例默认值,请务必小心,不要混淆同一值的其他实例。这可能会在反序列化对象时发生,您需要使用 readResolve() 等来确保正确的单例值被放置。
在我看来,您应该优先考虑将 null 用作默认值。
- 它略微更快且使用的内存更少 - 它更有可能帮助您检测逻辑错误(通过大声的 NullPointerException 而不是使用默认值代替实际值导致难以跟踪的 bug)。

谢谢,mikera。是的,看起来我们非常一致地使用了不可变的单例对象,就像你说的那样。你知道吗,最初编写代码的那个人正在要求我调查空值 ;) - f1dave

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接