假设您正在使用一个简单的类并且对象创建并不繁重:
class Simple {
public final int data1;
public final float data2;
...
}
您必须不断地将简单对象放入队列中:
queue.add(new Simple(123,123f,...));
使用 Object-Pool 并更改 Simple-Class 可修改类是否更快?我希望不是。
假设您正在使用一个简单的类并且对象创建并不繁重:
class Simple {
public final int data1;
public final float data2;
...
}
您必须不断地将简单对象放入队列中:
queue.add(new Simple(123,123f,...));
使用 Object-Pool 并更改 Simple-Class 可修改类是否更快?我希望不是。
一般来说,不,它不会更快。如果您将 JVM 配置为使用“吞吐量”GC,您将通过不尝试回收对象获得更好的性能。仅当您“内存受限”或 GC 暂停有问题时才值得考虑对象池。(根据世代假设,随着垃圾与非垃圾的比例增加,垃圾收集对象的摊销成本趋于零,特别是如果对象“年轻时死去”。)
实际上:
如果应用程序是多线程的,对象池很可能是并发瓶颈,并且
“有效不可变”对象的突变可能需要额外的开销和/或额外的同步。
如果对象创建速率是“每秒大约 20 个对象”,那么使用对象池不太可能对性能产生显着影响,即使它产生了改进(我对此表示怀疑)。
算一算。
如果对象大小为Simple
N 字节,并且您每秒分配 M,您可以估计每秒分配的字节数。
如果您的“年轻空间”是 Y MB,则根据该分配率触发 GC 需要 T 秒。
如果“年轻空间”GC 对于大小为 Y 的空间平均占用 G ms,您可以估计假设可以节省的时间的上限……假设对象池的相关开销为零。
实际节省的费用会更少,因为“零开销”假设是不现实的。
事实上,做一个“年轻空间”系列所花费的时间不仅仅取决于它的大小。它还取决于需要保留的非垃圾量。(保留的非垃圾越少越好!)这会使 GC 开销难以估计。但是,如果您已经在没有对象池的情况下编写了应用程序,则可以测量具有典型工作负载的应用程序的平均“年轻空间”收集时间,然后将其插入上面的计算中。
如果您确实在创建一些重对象或者您有其他要求指定对象池的需要,则对象池是有意义的。否则,我只会创建新对象并依靠 JVM 来摆脱所有不需要的对象(请记住首先删除/重新分配对不需要对象的引用)