我目前正在尝试为竞赛构建一些代码执行优化,并且正在研究ObjectPool模式以支持对象重用而不是新的对象实例化。
我整理了一个small project(以及only test class)来调查我看到和不理解的一些事情。
我在做什么:
我的结果是:
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
我从中注意到了什么:
我在这里寻找的是理解这些结果,并指出我可以阅读的文档/书籍,以便了解这些情况下幕后发生的事情。
谢谢!
答案 0 :(得分:5)
正如Mike Nakis的评论中提到的,随机参数测试与固定参数测试之间的差异完全是由于生成随机数的费用,更公平的测试可能是生成1000万条目在使用循环之前将随机整数数组(初始化Point
所需的每个参数为1)并将其与您选择的1000万个数字输入数组(即1和2)进行比较,就像您要比较的那样比如,不包括测试结果中随机数生成的费用。
你的游戏池每次初始化(至少就执行时间而言)的性能比初始化更糟糕的原因是因为你存储在游泳池中的对象是一个相对简单的对象,几乎可以立即使用初始化。因此,您正在评估的条件语句:
if (pointIndex >= POINT_POOL_SIZE) {
pointIndex = pointIndex - POINT_POOL_SIZE;
totalPointLoops++;
}
以及索引数组,需要比Point
对象初始化所需的更多执行时间。
您可能在示例中节省了一些内存,但是这似乎不太可能,因为您从池中获取的对象永远不会释放回池中以供重用(从我在代码中看到的内容)。 另外一个简单的循环可能不是测试对象池的最佳方法,因为对象池的目的是拥有一个对象的缓存,这些对象的创建成本很高/容易出现故障/等等,并且它们的使用时间往往比简单的循环迭代,你很可能一次只使用一个对象。
以下是Java中对象池信息的一些很好的链接: