优化大型Java数据阵列的处理和管理

优化大型Java数据阵列的处理和管理,java,arrays,performance,optimization,memory-management,Java,Arrays,Performance,Optimization,Memory Management,我正在编写一些相当CPU密集的并发数字代码,这些代码将处理存储在Java数组中的大量数据(例如,大量双倍[100000]秒)。一些算法可能在几天内运行数百万次,因此获得最大的稳态性能是一个高度优先事项 本质上,每个算法都是一个Java对象,具有类似以下内容的方法API: public double[] runMyAlgorithm(double[] inputData); 或者,可以将引用传递到数组以存储输出数据: public runMyAlgorithm(double[] in

我正在编写一些相当CPU密集的并发数字代码,这些代码将处理存储在Java数组中的大量数据(例如,大量双倍[100000]秒)。一些算法可能在几天内运行数百万次,因此获得最大的稳态性能是一个高度优先事项

本质上,每个算法都是一个Java对象,具有类似以下内容的方法API:

   public double[] runMyAlgorithm(double[] inputData);
或者,可以将引用传递到数组以存储输出数据:

   public runMyAlgorithm(double[] inputData, double[] outputData);
鉴于这一需求,我正试图确定分配/管理阵列空间的最佳策略。算法通常需要大量的临时存储空间。他们还将使用大型数组作为输入,并创建大型数组作为输出

我正在考虑的方案包括:

  • 在需要时,始终将新数组作为局部变量分配(例如,新的双精度[100000])。可能是最简单的方法,但会产生大量垃圾
  • 预先分配临时数组,并将它们存储为算法对象中的最终字段——最大的缺点是,这意味着在任何时候只有一个线程可以运行算法
  • 将预先分配的临时阵列保留在ThreadLocal存储中,以便线程可以在需要时使用固定数量的临时阵列空间。由于多个线程将同时运行相同的算法,因此需要ThreadLocal
  • 将大量数组作为参数传递(包括要使用的算法的临时数组)。不太好,因为如果调用者必须负责提供临时数组空间,则会使算法API非常难看
  • 分配非常大的数组(例如,double[10000000]),但也为算法提供数组中的偏移量,以便不同的线程将独立使用数组的不同区域。显然需要一些代码来管理数组范围的偏移和分配

关于哪种方法是最好的(以及为什么)?

在Java中使用内存时,我注意到以下几点。如果您的内存需求模式很简单(主要是2-3种类型的内存分配),那么您通常可以比默认的分配器更好。您可以在应用程序启动时预先分配一个缓冲池,并根据需要使用它们,也可以转到另一个路径(在开始时分配一个大型阵列,并在需要时提供其中的一部分)。实际上,您正在编写自己的内存分配器。但很可能您的工作会比Java的默认分配器差

我可能会尝试执行以下操作:标准化缓冲区大小并正常分配。这样,一段时间后,唯一的内存分配/释放将是固定大小的,这将极大地帮助垃圾收集器快速运行。我要做的另一件事是确保在算法设计时,任何一点所需的总内存不会超过机器内存的80-85%,以免无意中触发完全收集


除了这些启发式,我可能会测试我选择的任何解决方案,看看它在实践中是如何工作的。

在Java中使用内存时,我注意到以下几点。如果您的内存需求模式很简单(主要是2-3种类型的内存分配),那么您通常可以比默认的分配器更好。您可以在应用程序启动时预先分配一个缓冲池,并根据需要使用它们,也可以转到另一个路径(在开始时分配一个大型阵列,并在需要时提供其中的一部分)。实际上,您正在编写自己的内存分配器。但很可能您的工作会比Java的默认分配器差

我可能会尝试执行以下操作:标准化缓冲区大小并正常分配。这样,一段时间后,唯一的内存分配/释放将是固定大小的,这将极大地帮助垃圾收集器快速运行。我要做的另一件事是确保在算法设计时,任何一点所需的总内存不会超过机器内存的80-85%,以免无意中触发完全收集


除了这些启发式方法,我可能会测试我选择的任何解决方案,看看它在实践中是如何工作的。

对于GC来说,分配大数组相对便宜。您倾向于快速使用您的伊甸园空间,但成本主要是每个对象。我建议您以尽可能最简单的方式编写代码,并在分析应用程序之后对其进行优化。双精度[100000]小于1MB,在GB中可以超过1000


内存比以前便宜多了。一台8GB服务器的成本约为850英镑。一台24 GB服务器的成本约为1800英镑。(一台24 GB的机器可以允许您使用24K x double[100000])您可能会发现,使用较大的堆大小,甚至是较大的Eden大小,都可以获得所需的效率。

对于GC来说,分配较大的阵列相对便宜。您倾向于快速使用您的伊甸园空间,但成本主要是每个对象。我建议您以尽可能最简单的方式编写代码,并在分析应用程序之后对其进行优化。双精度[100000]小于1MB,在GB中可以超过1000

内存比以前便宜多了。一台8GB服务器的成本约为850英镑。一台24 GB服务器的成本约为1800英镑。(一台24 GB的机器可以让您使用24K x double[100000])您可能会发现,使用较大的堆大小,甚至是较大的Eden大小,都可以提供所需的效率