Java - 对象池与新对象实例化的性能

时间:2017-01-28 09:33:14

标签: java performance object-pooling

我目前正在尝试为竞赛构建一些代码执行优化,并且正在研究ObjectPool模式以支持对象重用而不是新的对象实例化。

我整理了一个small project(以及only test class)来调查我看到和不理解的一些事情。

我在做什么:

  • 使用new()和Pool.get()操作比较为5 000 000次迭代创建非常简单的对象
  • 围绕三个轴进行游戏,使用和不使用以下所有测试:
    • 在进行测量之前运行循环一次的“预热”
    • 将新创建的对象分配给局部变量并将其用于某些计算
    • 使用固定vs随机参数作为参数

我的结果是: Figures are for new instantiation vs with object pool for 5 000 000 iterations without_warmup_without_new_object_use_with_random_parameters: 417 vs 457 without_warmup_without_new_object_use_with_fixed_parameters: 11 vs 84 without_warmup_with_new_object_use_with_random_parameters: 515 vs 493 without_warmup_with_new_object_use_with_fixed_parameters: 64 vs 90 with_warmup_without_new_object_use_with_random_parameters: 284 vs 419 with_warmup_without_new_object_use_with_fixed_parameters: 8 vs 55 with_warmup_with_new_object_use_with_random_parameters: 410 vs 397 with_warmup_with_new_object_use_with_fixed_parameters: 69 vs 82

我从中注意到了什么:

  • 使用固定参数在实例化新对象时不会重复使用会产生巨大影响。我的猜测是编译器正在进行某种优化并发现没有副作用并且会完全删除对象实例化,但是将perfs与空循环进行比较表明仍然会发生某些事情
  • 使用固定参数对新Object()的速度有显着影响(虽然不太明显),在某些情况下使其比对象池版本更快
  • 对象池在“现实生活”场景中更快(即重用新对象并使用一些随机参数),但在大多数情况下都没有,这也暗示了编译器的优化。

我在这里寻找的是理解这些结果,并指出我可以阅读的文档/书籍,以便了解这些情况下幕后发生的事情。

谢谢!

1 个答案:

答案 0 :(得分:5)

固定参数

正如Mike Nakis的评论中提到的,随机参数测试与固定参数测试之间的差异完全是由于生成随机数的费用,更公平的测试可能是生成1000万条目在使用循环之前将随机整数数组(初始化Point所需的每个参数为1)并将其与您选择的1000万个数字输入数组(即1和2)进行比较,就像您要比较的那样比如,不包括测试结果中随机数生成的费用。

性能

你的游戏池每次初始化(至少就执行时间而言)的性能比初始化更糟糕的原因是因为你存储在游泳池中的对象是一个相对简单的对象,几乎可以立即使用初始化。因此,您正在评估的条件语句:

if (pointIndex >= POINT_POOL_SIZE) {
            pointIndex = pointIndex - POINT_POOL_SIZE;
            totalPointLoops++;
        }

以及索引数组,需要比Point对象初始化所需的更多执行时间。

您可能在示例中节省了一些内存,但是这似乎不太可能,因为您从池中获取的对象永远不会释放回池中以供重用(从我在代码中看到的内容)。 另外一个简单的循环可能不是测试对象池的最佳方法,因为对象池的目的是拥有一个对象的缓存,这些对象的创建成本很高/容易出现故障/等等,并且它们的使用时间往往比简单的循环迭代,你很可能一次只使用一个对象。

相关信息

以下是Java中对象池信息的一些很好的链接: