对象池与不可变对象

Objectpool vs. immutable Objects

假设您正在使用一个简单的 class 并且对象创建并不繁重:

class Simple {
  public final int data1;
  public final float data2;
  ...
}

您必须不断地将简单对象放入队列中:

queue.add(new Simple(123,123f,...));

使用 Object-Pool 并更改 Simple-Class 可修改 class 是否更快?我希望不会。

如果您确实要创建一些重对象,或者您有其他指定需要对象池的要求,则对象池很有意义。否则我会继续创建新的并依靠 JVM 来摆脱所有不需要的东西(记住 delete/re-assign 首先引用不需要的对象)

一般来说,不,它并不快。如果您将 JVM 配置为使用 "throughput" GC,您将通过不尝试回收对象来获得更好的性能。只有当你是 "memory constrained" 或者 GC 暂停有问题时才值得考虑对象池。 (随着垃圾与非垃圾比例的增加,垃圾收集对象的摊销成本趋于零,特别是如果对象 "die young",根据世代假设。)

事实上:

  • 如果应用是多线程的,对象池很可能是并发瓶颈,并且

  • "effectively immutable" 对象的变化可能需要额外的开销and/or 额外的同步。


如果对象创建率是 "about 20 objects per second",那么使用对象池不太可能对性能产生显着影响,即使它产生了改进(我对此表示怀疑)。

计算一下。

  • 如果 Simple 的对象大小为 N 字节,而您每秒分配 M 字节,则可以估计每秒分配的字节数。

  • 如果您的 "young space" 是 Y Mbytes,根据该分配率将需要 T 秒来触发 GC。

  • 如果 "young space" GC 对于大小为 Y 的 space 平均花费 G 毫秒,您可以估计时间上限 假设 被保存...假设对象池的相关开销为零。

  • 实际节省的会少一些,因为"zero overheads"假设不现实

事实上,完成 "young space" 收集所花费的时间不仅仅取决于它的大小。它还取决于需要保留的非垃圾数量。 (保留的非垃圾越少越好!)这会使 GC 开销难以估计。但是,如果您已经编写了没有对象池的应用程序,则可以测量具有典型工作负载的应用程序的平均 "young space" 收集时间,然后将其代入上述计算。