创建数百万个小型临时对象的最佳实践

112

创建(和释放)数百万个小对象的最佳实践是什么?

我正在使用Java编写一个象棋程序,搜索算法为每个可能的移动生成单个“Move”对象,而标准搜索可以轻松生成每秒超过一百万个移动对象。 JVM GC已能够处理开发系统上的负载,但我有兴趣探索替代方法,以便:

  1. 最小化垃圾回收的开销,以及
  2. 减少较低端系统的峰值内存占用。

绝大多数对象的寿命非常短,但是生成的移动中约有1%会被持久化并返回作为持久化值,因此任何缓存技术都必须提供排除特定对象不被重用的能力。

我不希望完全详细的示例代码,但我希望获得进一步阅读/研究建议或具有类似性质的开源示例。


11
轻量级模式适用于您的情况吗?http://en.wikipedia.org/wiki/Flyweight_pattern - Roger Rowland
4
你需要将它封装在一个对象中吗? - nhahtdh
1
享元模式不适用,因为对象没有共享重要的公共数据。至于将数据封装在对象中,它太大了,无法打包成原始对象,这就是为什么我正在寻找POJO的替代方案。 - Humble Programmer
2
强烈推荐阅读:http://www.cs.virginia.edu/kim/publicity/pldi09tutorials/memory-efficient-java-tutorial.pdf - rkj
13个回答

0

对象池在堆上分配对象时提供了巨大的(有时是10倍)性能提升。但是使用链表的上述实现既幼稚又错误!链表创建对象来管理其内部结构,使得这种努力无效。 使用对象数组的环形缓冲区效果很好。在给定的示例中(一个管理移动的棋类程序),环形缓冲区应该被包装到一个包含所有计算出的移动列表的持有者对象中。然后只传递移动持有者对象引用。


0

只需创建数百万个对象并以正确的方式编写代码:不要保留这些对象的不必要引用。垃圾回收器将为您完成脏活。您可以尝试使用详细的垃圾回收器来查看它们是否真正被回收。Java就是关于创建和释放对象的。 :)


1
抱歉,伙计,我不同意你的方法... Java,像任何编程语言一样,都是关于在其限制内解决问题的,如果OP受到GC的限制,你如何帮助他呢? - Nitsan Wakart
1
我正在告诉他Java的实际工作原理。如果他无法避免拥有数百万个临时对象的情况,最好的建议是,临时类应该轻量级,并确保尽快释放引用,不再有任何一步。我有什么遗漏吗? - gyorgyabraham
Java支持创建垃圾,并会为您清理它,这是真的。如果OP无法避免创建对象,并且他对在GC中花费的时间感到不满,那么这是一个悲伤的结局。我的反对意见是针对您建议增加GC工作量的建议,因为这在某种程度上是正确的Java。 - Nitsan Wakart

0
我认为你应该了解一下Java中的堆栈分配和逃逸分析。
因为如果你深入研究这个话题,你可能会发现你的对象甚至不是在堆上分配的,并且它们不会像堆上的对象那样被垃圾回收器收集。
维基百科有一个关于逃逸分析的解释,其中包含了Java中这个机制的示例。

http://en.wikipedia.org/wiki/Escape_analysis


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