Java 使用JRE-Xms300m可以将我的执行时间减半吗?

Java 使用JRE-Xms300m可以将我的执行时间减半吗?,java,Java,大家好,我想知道是否有人能提供一些解释或证实我的猜测 我有一个带有for循环的程序,它执行了几十万次,每次都向一组数组列表中添加数字。我不明白为什么执行死刑要花这么长时间,于是进一步调查 结果是如果我有 (for int i =0; i < 50000; i++) 通过为ArrayList指定初始大小,可以为元素的引用保留空间,而不是元素本身。每次调用add(),都会创建一个新的Integer对象,并将其添加到基础数组中,这些对象很可能正在吞噬您的堆 我有点惊讶,仅仅添加-Xms300m

大家好,我想知道是否有人能提供一些解释或证实我的猜测

我有一个带有for循环的程序,它执行了几十万次,每次都向一组数组列表中添加数字。我不明白为什么执行死刑要花这么长时间,于是进一步调查

结果是如果我有

(for int i =0; i < 50000; i++)

通过为
ArrayList
指定初始大小,可以为元素的引用保留空间,而不是元素本身。每次调用
add()
,都会创建一个新的
Integer
对象,并将其添加到基础数组中,这些对象很可能正在吞噬您的堆

我有点惊讶,仅仅添加-Xms300m就可以帮助设置最小堆大小,但没有设置最大值(使用-Xmx),您通常会看到一个错误:

$ java -Xms300m blah
Error occurred during initialization of VM
Incompatible minimum and maximum heap sizes specified
当Java应用程序创建大量对象并接近堆限制时,JVM开始执行垃圾收集(GC),这主要包括两个步骤:

  • 搜寻不再使用且可以释放的对象
  • 将已经存在一段时间的对象整合到堆的不同部分(“旧”或“终身生成”)——这意味着未来的GC运行可以忽略这些对象,从而提高性能

关于Java的GC机制(包括)有很多深入的文档,但对于初学者来说,要了解程序中发生了什么,请尝试添加
-verbose:GC
标志。每次垃圾回收器启动时,它都会输出一行,告诉您它运行了多长时间以及释放了多少内存,当您增加迭代次数时,这可能会为您提供堆中发生了什么的线索。

通过为
ArrayList
指定初始大小,您为元素的引用保留了空间,而不是元素本身。每次调用
add()
,都会创建一个新的
Integer
对象,并将其添加到基础数组中,这些对象很可能正在吞噬您的堆

我有点惊讶,仅仅添加-Xms300m就可以帮助设置最小堆大小,但没有设置最大值(使用-Xmx),您通常会看到一个错误:

$ java -Xms300m blah
Error occurred during initialization of VM
Incompatible minimum and maximum heap sizes specified
当Java应用程序创建大量对象并接近堆限制时,JVM开始执行垃圾收集(GC),这主要包括两个步骤:

  • 搜寻不再使用且可以释放的对象
  • 将已经存在一段时间的对象整合到堆的不同部分(“旧”或“终身生成”)——这意味着未来的GC运行可以忽略这些对象,从而提高性能

关于Java的GC机制(包括)有很多深入的文档,但对于初学者来说,要了解程序中发生了什么,请尝试添加
-verbose:GC
标志。每次垃圾回收器启动时,它都会输出一行,告诉您运行所需的时间和释放的内存量,这可能会为您提供增加迭代次数时堆中发生的情况的线索。

是的,-Xms选项指定起始堆空间。如果这加快了问题的速度,那么很可能您遇到了内存分配/垃圾收集问题。请注意ArrayList API:

“每个ArrayList实例都有一个容量。容量是用于存储列表中元素的数组的大小。它始终至少与列表大小一样大。当元素添加到ArrayList时,其容量会自动增长。除了添加要素具有恒定的摊余时间成本这一事实之外,没有详细说明增长政策

应用程序可以在使用ensureCapacity操作添加大量元素之前增加ArrayList实例的容量。这可能会减少增量重新分配的数量。 "

因此,ArrayList如何添加内存是JVM的一个实现细节,但有固定的摊销成本


我打赌您正在数组中创建对象,在40k到50k次迭代之间,您的程序尝试GC,失败了,然后添加了更多堆。指定更高的最小值会延迟GC和更多堆创建…

是的,-Xms选项指定了起始堆空间。如果这加快了您的问题,那么很可能您已经运行了正在处理内存分配/垃圾收集问题。请注意ArrayList API:

“每个ArrayList实例都有一个容量。容量是用于存储列表中元素的数组的大小。它始终至少与列表大小一样大。当元素添加到ArrayList时,其容量会自动增长。除了添加要素具有恒定的摊余时间成本这一事实之外,没有详细说明增长政策

应用程序可以在使用ensureCapacity操作添加大量元素之前增加ArrayList实例的容量。这可能会减少增量重新分配的数量。 "

因此,ArrayList如何添加内存是JVM的一个实现细节,但有固定的摊销成本


我打赌您正在数组中创建对象,在40k到50k次迭代之间,您的程序尝试GC,失败,然后添加更多堆。指定更高的最小值将延迟GC和更多堆创建…

@hvgotcodes的回答是:

我打赌您正在数组中创建对象,在40k和50k次迭代之间,您的程序尝试GC,失败,然后添加更多堆。指定更高的最小值将延迟GC和更多堆创建

这很接近实际情况,但可能并不完全正确

使用Java 1.6 Hotspot JVM,堆将在两种情况下扩展:

  • 垃圾收集之后,仍然没有足够的可用空间来分配对象
    $ java -Xms300m blah
    Error occurred during initialization of VM
    Incompatible minimum and maximum heap sizes specified