对象池或通过引用传递无状态对象

时间:2010-01-18 07:47:17

标签: java

我反复构建一个有20个字段的对象。该对象由单线程构造和使用。

我打算使用池或构造对象一次,并将其作为参数传递给相关方法。完成后,将所有字段设置为NULL。一次又一次地重复使用同一个对象。

我的问题是,这种方法会改善效果吗?因为我可以推迟创建100,000个对象(有时甚至更多)。但是我需要为每个字段设置null,这个overahead是否会与对象创建相等。

4 个答案:

答案 0 :(得分:4)

如果在创建对象时不需要进行昂贵的初始化,我就不会打扰了。依靠运行时有效地进行内存管理。如果您最终发现应用程序中的瓶颈是对象的实际分配,您可以尝试进一步优化(尽管我怀疑将所有字段重置为默认值会更快,很可能不会)。

一般规则是:不要过早(微观)优化: - )

答案 1 :(得分:1)

不要那样做。您的微优化可能会更慢。

对象创建可能是Java 1.0的性能瓶颈,但现在不再存在。现在汇集对象的唯一原因是具有与之关联的重要资源的事物,例如数据库连接和线程。

答案 2 :(得分:0)

我建议不要将内存池用于除了构建起来非常昂贵的外部资源之外的任何东西,作为数据库连接或线程。 GC处理短期对象非常有效,因此创建和删除(遗忘)对象非常有效。

创建新元素和维护旧元素都存在相关成本。在两种情况下,字段的设置(值分配)都是类似的,因此您需要比较的是其他相关成本。

对于新分配的对象,第二个成本是内存分配。使用当前垃圾收集器的Java托管内存环境在分配内存方面非常有效。与操作系统需要找到适当的内存块来分配的C / C ++相比,生成GC保证内存是连续的,因此分配非常快。在一些Java 1.4实现中,只需要少于10条CPU指令即可。重新分配年轻物体(那些没有通过第一次GC运行的物体)也很快:它们被简单地忽略 - 除非它们有终结器,应该尽可能地避免。

另一方面,GC运行中存在的年轻对象必须在每次GC运行时从一部分内存移动到另一部分。在对象被认为足够老以进入老一代之前可能会发生这种情况,有可能它会移动得更少(它仍然可以在老一代的压缩GC中运行)。

长寿命对象的另一个问题是它们无法引用更年轻的对象。当发生这种情况时(将new X()分配给旧对象),必须将长寿命对象重新分配给最新一代,这也可能意味着成本,因为它可能需要将对象从旧一代区域移动到新一代区域,这将在旧一代内存中留下一个漏洞,可能会迫使下一代旧版GC运行中的移动对象压缩内存。

总而言之,重要的是,有许多非常聪明的人在语言,编译器和垃圾收集器中工作。所有这些人都会努力提高最常见的习惯用语的性能,并试图超越系统可能会让你走出一条柔软顺畅的道路。

答案 3 :(得分:0)

我肯定会尝试一下。虽然现在是“常识”,人们不应该关心对象创建,但实际上使用对象池和特定类可能会获得很多性能。对于文件处理框架,我从pooling object []对象中获得了5%的读取性能。