Java 重复的对象分配性能影响
Java repeated object allocations perfomance impact
为什么 LinkedList 对于大 n 比常规数组(没有新分配)慢 10 倍:
Deque<Boolean> tail = new LinkedList<>();
for (int i = 1; i <= n; i++) {
tail.addFirst(true);
tail.pollLast();
}
我的第一个猜测是 gc 时间,但它只需要 3.5 秒中的 100 毫秒。
找出这背后原因的最佳方法是什么?
Whats the best way to locate the reason behind this?
方法有很多种:
将您的示例转换为适当的基准并运行 使用分析器。然后看看时间花在了哪里
查看您正在调用的 LinkedList 方法的源代码。
检查 Javac 编译器为您的代码和 LinkedList 代码生成的字节码。
检查 JIT 编译器为您的代码和 LinkedList 代码生成的本机代码。
(我会让你自己调查这个,因为我怀疑它会显示出任何特别出乎意料的东西。)
My first guess was gc time but it takes 100 ms out of 3.5 sec only.
很可能大部分时间用于分配和初始化链表节点对象,以及列表方法的其他开销。
如果 GC 在构建列表时确实需要 运行,那么 LinkedList
情况下的 GC 开销会比数组情况大一点。但我怀疑实际发生的事情是 GC 实际上正在回收在代码加载和(可能)JIT 编译期间创建的对象。在列表/数组构建过程中产生的实际可收集垃圾的数量 应该是 零......在这两种情况下。
您的 基准测试方法 也可能扭曲了结果。例如,我注意到您的 pollLast
调用没有做任何有用的事情......关于构建列表。另一个问题可能是您不允许 JVM 预热效果。
一般来说,您看到的 10 倍差异对应于 "received wisdom" Java 列表与数组的性能。如果您使用 ArrayList
而不是 LinkedList
,性能将更接近裸阵列,特别是如果您对 ArrayList
容量给出了很好的估计。
为什么 LinkedList 对于大 n 比常规数组(没有新分配)慢 10 倍:
Deque<Boolean> tail = new LinkedList<>();
for (int i = 1; i <= n; i++) {
tail.addFirst(true);
tail.pollLast();
}
我的第一个猜测是 gc 时间,但它只需要 3.5 秒中的 100 毫秒。 找出这背后原因的最佳方法是什么?
Whats the best way to locate the reason behind this?
方法有很多种:
将您的示例转换为适当的基准并运行 使用分析器。然后看看时间花在了哪里
查看您正在调用的 LinkedList 方法的源代码。
检查 Javac 编译器为您的代码和 LinkedList 代码生成的字节码。
检查 JIT 编译器为您的代码和 LinkedList 代码生成的本机代码。
(我会让你自己调查这个,因为我怀疑它会显示出任何特别出乎意料的东西。)
My first guess was gc time but it takes 100 ms out of 3.5 sec only.
很可能大部分时间用于分配和初始化链表节点对象,以及列表方法的其他开销。
如果 GC 在构建列表时确实需要 运行,那么 LinkedList
情况下的 GC 开销会比数组情况大一点。但我怀疑实际发生的事情是 GC 实际上正在回收在代码加载和(可能)JIT 编译期间创建的对象。在列表/数组构建过程中产生的实际可收集垃圾的数量 应该是 零......在这两种情况下。
您的 基准测试方法 也可能扭曲了结果。例如,我注意到您的 pollLast
调用没有做任何有用的事情......关于构建列表。另一个问题可能是您不允许 JVM 预热效果。
一般来说,您看到的 10 倍差异对应于 "received wisdom" Java 列表与数组的性能。如果您使用 ArrayList
而不是 LinkedList
,性能将更接近裸阵列,特别是如果您对 ArrayList
容量给出了很好的估计。