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

Séb*_*omp 4 java performance object-pooling

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

我已经组建了一个小项目(和唯一的测试类)来调查我看到和不理解的一些事情.

我在做什么:

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

我得到的结果是: 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()的速度有显着影响(虽然不太明显),在某些情况下使其比对象池版本更快
  • 对象池在"现实生活"场景中更快(即重用新对象并使用一些随机参数),但在大多数情况下都没有,这也暗示了编译器优化.

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

谢谢!

小智 6

固定参数

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

性能

你的池每次初始化(至少就执行时间而言)表现差的原因是因为你存储在池中的对象是一个相对简单的对象,几乎没有时间初始化.因此,您正在评估的条件语句:

if (pointIndex >= POINT_POOL_SIZE) {
            pointIndex = pointIndex - POINT_POOL_SIZE;
            totalPointLoops++;
        }
Run Code Online (Sandbox Code Playgroud)

以及索引数组,需要比Pointinit对象需要更多的执行时间.

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

相关信息

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