【问题标题】:Performant way of nullifying all fields of an object使对象的所有字段无效的高效方法
【发布时间】:2019-03-30 12:14:57
【问题描述】:

我有一个简单的 pojo 类,其中包含 20 多个字段和对性能敏感的一段代码。为了减少分配,我重用了该类的相同实例。 如何以最高效(不安全)的方式清理对象?

如果我没有弄错字段数据存储为连续的字节序列,那么我希望一定有像 System.arraycopy 这样快的东西。

类本身是稳定 API 的一部分,不能修改。

【问题讨论】:

  • 我想说让垃圾收集器完成它的工作。你用过探查器吗?你确定有必要吗? Related.
  • 最高效的方法可能是不去这些长度并分配一个新对象而不是重用旧对象。
  • @dustytrash 我问过我们的建筑师同样的问题,答案是“是”
  • 调用 20 个简单的 setter 是一种廉价的操作。它只需要几纳秒。我很确定这不是值得优化的东西。
  • @apangin 我写了一个 jmh 基准。你是完全正确的。谢谢。

标签: java performance


【解决方案1】:

调用 20 个简单的 setter 是一种廉价的操作。它只需要几纳秒。我很确定这不是值得优化的东西。

以直接的方式逐个设置字段已经足够优化。理论上,使用 SIMD 指令可以更快地清除对象,但在 Java 中没有办法做到这一点。

有一个方法Unsafe.setMemory,但它只适用于原始数组。这个限制很容易理解:使用批量操作清除具有引用字段的对象是无效的,因为不同的 GC 可能需要单独跟踪对引用字段的更新。

如果您查看Arrays.fill 的实现,它使用一个简单的循环来逐个存储元素,并且由于上述原因,该方法甚至不是JVM 固有的。

【讨论】:

    【解决方案2】:

    如前所述,其背后的推理非常值得怀疑。

    我们不想使用反射,因为众所周知它很慢。您是否考虑使用 Java 字节码操作库(Javassist、Bytebuddy、..),它允许您修改 Pojo 类并添加一个附加方法,该方法将直接将所有字段设置为 null

    【讨论】:

    • 我已经有了修改字段的设置器。所以不需要字节码黑客。但是需要 20 多个方法调用才能使所有字段无效。
    【解决方案3】:

    假设您想始终同时取消所有字段,那么最简单的方法是拥有一个包含所有值的内部对象。让您的 getter 和 setter 成为该对象字段周围的轻包装器。然后,不要单独使字段无效,只需使用字段以 null 开头的新实例刷新内部对象。

    【讨论】:

    • 不幸的是,它相当于只是创建一个新对象。相同数量的分配,相同的内存占用。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-11-13
    • 1970-01-01
    • 2017-06-04
    • 2022-08-18
    • 2017-02-26
    • 2022-10-14
    • 2018-01-03
    相关资源
    最近更新 更多