使用null而不是默认值获得性能提升?

时间:2011-05-12 13:30:37

标签: java performance optimization memory

他们说过早的优化是所有邪恶的根源,但这里就是......

我们有一个高性能的应用程序;服务器端由Java支持的内存缓存,以及客户端需要非常快速的C#GUI。

我注意到目前我们在缓存中使用的对象具有默认值 - 例如将字符串默认初始化为“”并将日期初始化为1/1/1999,而不是将它们保留为空。

现在我可能在这里非常挑剔,但这不会为每个对象增加一点点空间(在缓存中和对象被序列化时),如果它为null则不会增加它们的空间吗?

只是想知道当我们的对象数量开始变得很高时会获得什么样的改进(如果有的话)......

干杯, 戴夫。

1 个答案:

答案 0 :(得分:3)

过早优化肯定是邪恶的。

但是,如果性能是应用程序的关键要求,那么考虑应用程序的性能特征以及优化性能的适当设计策略是完全合理的: - )

一些相关要点:

  • 使用null 而不是默认值会有一些(轻微的)性能优势。本机代码检查空值比取消引用对象引用并检查该对象的值更容易。如果所有内容都在L1缓存中,您可能不会注意到这一点,但如果这导致高性能应用程序中的缓存未命中,则可能会变得很痛苦。
  • 有一些额外的内存开销,但它可能并不重要 - 假设你多次重复使用相同的默认值对象(即许多键指向相同的值),那么就不会有很多额外的对象实例整体。
  • 如果您的默认值是不可变,单例对象,那么它有很大帮助,原因有三:
    • 您只需要一个不可变对象的副本,而不是“”(String.intern()帮助的不同实例!)
    • 多次使用的单个对象更有可能被高效缓存
    • 您可以使用引用相等(值== DEFAULT_SINGLETON)来测试默认值,这样可以避免在DEFAULT_SINGLETON是静态最终值时需要指针取消引用。
  • 如果您确实使用了不可变的单例默认值,请务必小心不要将任何其他具有相同值的实例混入。例如,这可能会发生。反序列化对象时 - 需要使用readResolve()等来确保获得正确的单例值。

在我看来,您应该更喜欢使用空值作为默认值。

  • 速度稍快,使用的内存较少
  • 更有可能帮助您检测逻辑错误(通过大声的NullPointerException,而不是导致难以跟踪的错误,使用默认值代替实际值)