У меня есть Java-приложение, которое обрабатывает довольно много данных.
Метод, который забирает всю память, выполняет следующее:
Это хвосто-рекурсивный метод (который я сделал стека-безопасно с трамполинированием), метод сначала выполняет итерации по LinkedList (который может содержать много объектов, до нескольких миллионов), и для каждого объекта я прохожу еще один цикл с int = 1 до 13.
private TailCall<LinkedList<HandInstance>>
setDealerHandsInstanceList(LinkedList<HandInstance> handInstanceList,
LinkedList<HandInstance> dealerHandInstanceList) {
final LinkedList<HandInstance> handInstanceListP = new LinkedList<>();
for (HandInstance handInstance : handInstanceList) {
Shoe shoe = handInstance.getShoe();
BigDecimal kansAlGespeeldeKaarten = handInstance.getKansAlGespeeldeKaarten();
int spelerTotaalInitiaal = handInstance.getSpelerTotaalInitiaal();
for (Kaart kaart : shoe.getDefaultHand()) {
//(--> defaultHand contains 13 elements)
Находясь в цикле defaultHand, я создаю новый handInstanceP, глубоко копирую атрибуты исходного handInstance и устанавливаю их в новый handInstanceP.(При изменении этих атрибутов также на основе цикла defaultHand. В соответствии с некоторым if-тестом, я добавляю этот handInstanceP в новый LinkedList handInstanceListP или dealerHandInstanceList
в конце цикла handInstanceList. Я делаю следующее:
if (!handInstanceListP.isEmpty()) {
return call(() -> setDealerHandsInstanceList(handInstanceListP,
dealerHandInstanceList));
} else {
Thread.dumpStack();
return TailCalls.done(dealerHandInstanceList);
}
Я уже пытался заглянуть в GC и настроить его параметры, но то, что я делаю, похоже, не работает.
При выполнении main я получаю OutOfMemoryErrors: 'java heapпробел »(когда я увеличил размер кучи до 2 ГБ) и« Превышен лимит накладных расходов ГХ »(когда я не установил никаких настроек, поэтому использую размеры и настройки по умолчанию) для самых требовательных запусков. Я работаю надWindows 10 с 8 ГБ оперативной памяти DDR4 (обратите внимание, что при запуске моей программы мне часто доступно только 4-5 ГБ)
Вопросы: Какой наиболее подходящий ГХ использовать? Параллельный ГХ, G1, последовательныйGC, UseConcMarkSweepGC?
Какие настройки GC мне нужно искать, в частности? Я думаю, есть много объектов, которые могутбыть назначенным только молодому поколению (см. объекты, объявленные сразу после оператора handInstanceList-loop-loop).(Например, у меня есть около 700 000 созданных int). Другие объекты являются более постоянными, как LinkedLists, но в основном это объекты в LinkList.Они созданы больше всего (около 8 миллионов раз и более на сложных пробегах).Я думаю, что они должны быть выделены старому поколению?Или можно сохранить их в молодом поколении и увеличить размер кучи молодого поколения?
Редактировать 1: я перешел на ArrayLists.
Редактировать 2: Действительно, это не реальноПроблема сбора мусора, больше попыток лениво обработать этот список в моей программе.Этот список существует только для целей расчета, как вы видите в конце цикла, я проверяю наличие пустого списка, поэтому в дальнейшем он мне не нужен.Мне нужно только изменить один конкретный объект, но для этого нужно много небольших изменений, и каждый цикл определяет одно небольшое изменение.
Если я использую потоки, у меня есть 2 вопроса.Если у меня есть следующее:
ArrayList<Class> list = new ArrayList<>();
Stream stream = list.stream()
stream.forEach(class ->
{
Class class2 = new Class();
class2.add(class);
// other things done with class2
});
Этот объект класса class2 лениво обрабатывается в моей программе, если он используется только и существует только в потоке forEach?
Другая возможность:
ArrayList<Class> list = new ArrayList<>();
Class class2 = new Class();
Stream stream = list.stream()
stream.forEach(class ->
{
class2.add(class);
});
Возможно ли это сделать?Это похоже на глупый вопрос, но я действительно не привык к потокам, я не знаю, что возможно, а что нет.Но это может показаться странным, если последний пример невозможен.