#java #performance #loops
#java #Производительность #циклы
Вопрос:
Я использую Win 7, Java 8 на многоядерной рабочей станции Intel. У меня есть что-то вроде этого :
int SampleWeeksArray[]=new int[]{23,25,33},IdArray[]=new int[]{0,1,2};
for (int StartDay=25;StartDay<36;StartDay )
for (int SampleWeeks : SampleWeeksArray)
for (int Id : IdArray)
for (float ValueFactor=0.08f;ValueFactor<0.13f;ValueFactor =0.01)
{
DataDigester dataDigester=new DataDigester();
dataDigester.StartDay=StartDay;
dataDigester.SampleWeeks=SampleWeeks;
dataDigester.Id=Id;
dataDigester.ValueFactor=ValueFactor;
dataDigester.DoRun();
}
Внутри dataDigester.DoRun() считывает некоторые текстовые файлы данных, анализирует каждую строку и выполняет некоторую статистику с массивами, векторами и хэш-картами, а также использует ThreadPoolExecutor для запуска нескольких процессов, а затем сохраняет результаты в файл.
Странно то, что каждый отдельный запуск DoRun() занимает всего 10 минут, но внутри циклов он начинается с 10 минут. но постепенно замедляется до 20, 30 мин. для каждого DoRun() .
Если я остановлю цикл, когда он займет 30 минут, а затем начну с того места, где я остановился, это снова займет 10 минут. и в конечном итоге замедляется до 20, 30 мин. снова. Почему?
Я даже вставил следующие строки после DoRun() , но это не улучшило скорость, все еще замедляется :
Thread.sleep(20*1000); // Rest for 20 seconds
System.gc();
Внутри каждого цикла DataDigester dataDigester=new DataDigester() создает новый объект, он должен быть переработан после DoRun(), почему он замедлился?
Я также заметил из диспетчера задач Windows, что использование памяти увеличивается по мере продолжения циклов. Кажется, Java каким-то образом обременяет себя чем-то и замедляется, поэтому в этом случае, как поддерживать скорость на постоянном уровне 10 мин. для каждого запуска в циклах?
Комментарии:
1. Может ли со временем появляться больше данных?
2. Не используйте double или float для итераторов. Это связано с тем, что плавающие типы неточны, и вы можете получить неожиданный результат. Также попробуйте использовать соглашения о коде Java, где переменные начинаются со строчных букв. например
for (int v = 8; v <= 13; v ) float valueFactor = v / 100.0f;
Ответ №1:
Трудно сказать, не зная, что такое DataDigester и что он делает, но я могу назвать несколько возможных причин:
-
если DataDigester.DoRun запускает новый поток — затем, по мере увеличения количества потоков, время, доступное для каждого потока, уменьшается. Если он использует аппаратные потоки, то время значительно увеличится, как только вы перейдете от 1 к 2 потокам на аппаратный поток.
-
DataDigester может иметь статическую структуру, к которой он добавляется, и которая становится все медленнее и медленнее, чем больше вы добавляете в нее
Комментарии:
1. Это то, что я подозревал, я изучу их, спасибо.
Ответ №2:
Объявите только один DataDigester
и повторно используйте его для всех ваших циклов вместо создания тысяч и тысяч из них.
int SampleWeeksArray[]=new int[]{23,25,33},IdArray[]=new int[]{0,1,2};
DataDigester dataDigester;
for (int StartDay=25;StartDay<36;StartDay )
for (int SampleWeeks : SampleWeeksArray)
for (int Id : IdArray)
for (float ValueFactor=0.08f;ValueFactor<0.13f;ValueFactor =0.01)
{
dataDigester=new DataDigester();
dataDigester.StartDay=StartDay;
dataDigester.SampleWeeks=SampleWeeks;
dataDigester.Id=Id;
dataDigester.ValueFactor=ValueFactor;
dataDigester.DoRun();
}
}
}
}
Это должно помочь с вашими проблемами сборки мусора, а также со сроками.
Комментарии:
1. Это было похоже на то, что вы предложили в начале, но я заметил замедление, поэтому я переместил DataDigester dataDigester; внутри циклов, я полагаю, он должен перерабатываться после каждого цикла и, следовательно, с постоянной скоростью. Но это не так.
2. Вы должны смотреть на то, что происходит внутри DataDigester для повышения производительности. И если DD.DoRun() запускает поток, возможно, при ограничении пула потоков, вы можете слишком часто менять потоки и довольно быстро увеличивать нагрузку на процессор.