Эти двое являются самыми большими убийцами:
private long[][][] dp = new long[29000][51][2]; // About 3*8 = 24 megabytes
private int[][][] init = new int[29000][51][2]; // About 3*4 = 12 megabytes
Например, если посмотреть на второго ... это не 12 мегабайт.У вас есть 29000 int[][]
объектов, каждый из которых содержит ссылки на 51 int[]
объектов, каждый из которых содержит 2 целых числа.
Предполагая 32-битный размер ссылки и 16издержки байтов для самого массива (длина + общая нагрузка на объект), что означает, что каждый int[][]
объект имеет размер 51 * 4 + 16 = 220 байт, а затем каждый объект int[]
имеет размер 24 байта.Но у вас есть 29000 * 51 из этих 24-байтовых объектов - что само по себе составляет 35 МБ ... Тогда есть 29000 int[][]
объектов, что составляет еще 6 МБ ... (Тогда есть сам массив верхнего уровня, ноэто всего лишь около 120 КБ.)
По сути, вы должны помнить, что Java не имеет многомерных массивов: у нее есть массивы массивов, и каждый массив является объектом с отдельными издержками.Я предлагаю вам вместо этого использовать:
private int[] init = new int[29000 * 51 * 2];
и самостоятельно отрабатывать соответствующие смещения.(То же самое для dp, что еще хуже, поскольку это long
значений, а не int
значений, поэтому каждый из массивов 29000 * 51 занимает по меньшей мере 32 байта, а не 24.)
Даже просто наоборотпорядок обработки измерений поможет :
private long[][][] dp = new long[2][51][29000];
private int[][][] init = new int[2][51][29000];
Теперь для каждой из этих переменных существует один массив массивов верхнего уровня, 2 массива-массивов и 102 массива long
или int
.Это соответствует много меньше накладных расходов.
Ваши другие вычисления тоже неверны, но я думаю, что эти два массива массивов являются худшими.