#java #multithreading #multicore #utilization
#java #многопоточность #многоядерный #использование
Вопрос:
У меня есть программа, которая сортирует большие файлы, разбивая их на фрагменты, сортируя фрагменты и объединяя их в окончательный отсортированный файл. Приложение запускает один поток для загрузки / сохранения данных из / в файл — только один поток выполняет операции ввода-вывода. Также есть еще два потока, которые получают фрагментные данные, сортируют их, а затем отправляют отсортированные данные обратно в поток, который выполняет ввод-вывод.
Таким образом, в целом выполняется 4 потока — основной поток, поток, который загружает / сохраняет данные, и два потока, которые сортируют данные.
Я думал, что во время выполнения я увижу 1 спящий поток (основной), который не требует никакого процессорного времени, и 3 активных потока, которые используют по 1 ядру процессора каждый.
Когда я запускаю эту программу на двухъядерном процессоре с 6 ядерными процессорами с hyper threading (24 процессора), я вижу, что ВСЕ 24 процессора загружены на 100%!
Изначально я думал, что алгоритм сортировки многопоточен, но после изучения источников Java я обнаружил, что это не так.
Я использую simple Collections.sort(LinkedList) для сортировки данных…
вот некоторые подробности:
# java - версия версия java "1.6.0_26" Среда выполнения Java (TM) SE (сборка 1.6.0_26-b03) 64-разрядная серверная виртуальная машина Java HotSpot (TM) (сборка 20.1-b02, смешанный режим) # uname -a Linux 2.6.32-28-server # 55-Ubuntu SMP Пн Янв 10 23:57:16 UTC 2011 x86_64 GNU / Linux
Я использовал nmon для мониторинга загрузки процессора.
Я был бы признателен за любое объяснение этого случая и любые советы о том, как контролировать загрузку процессора, поскольку эта конкретная задача не оставляет процессорного времени для других приложений
[ОБНОВЛЕНИЕ] Я использовал jvisualvm для подсчета потоков — он показывает только потоки, о которых я знаю. Также я создал простую тестовую программу (см. Ниже), которая запускает только один основной поток и получила точно такие же результаты — все 24 процессора заняты почти на 100% во время выполнения кода
public class Test {
public void run(){
Random r = new Random();
int len = r.nextInt(10) 5000000;
LinkedList<String> list = new LinkedList<String>();
for (int i=0; i<len; i ){
list.add(new String("test" r.nextInt(50000000)));
}
System.out.println("Inserted " list.size() " items");
list.clear();
}
public static void main(String[] argv){
Test t = new Test();
t.run();
System.out.println("Done");
}
}
[ОБНОВЛЕНИЕ]
Вот снимок экрана, который я сделал во время запуска программы выше (используется nmon):
http://imageshack.us/photo/my-images/716/cpuload.png /
Комментарии:
1. Вероятно, нам нужно просмотреть ваш код, чтобы понять это. Я предполагаю, что вы используете больше потоков, чем думаете.
2. Я использовал jvisualvm для подсчета потоков — он показывает только потоки, о которых я знаю. Также я создал простую тестовую программу, которая запускает только один основной поток и получила точно такие же результаты. пожалуйста, ознакомьтесь с моим обновлением, о котором идет речь.
3. 4 потока не могут использовать 100%-ную загрузку 6 ядер. Либо у вас больше потоков, либо ваши измерения неверны.
4. Какую программу вы используете для мониторинга загрузки процессора? Вероятно, он показывает вам какую-то другую программу, которая работает в фоновом режиме. Либо это, либо ваш тест настолько короткий, что он показывает вам только что-то, связанное с запуском JVM.
5. Я использовал nmon для мониторинга загрузки процессора, вот скриншот: ссылка Также, пока я не запускаю программу Java — она не показывает никакой активности. Во всяком случае, я вижу то же самое при запуске моей оригинальной программы сортировки. Честно говоря, я ожидал именно того, чего все ожидали бы — один поток использует один процессор. но похоже, что java использует зеленые потоки, которые не связаны с базовыми потоками ОС. Насколько я понимаю, java использует собственное планирование потоков. Таким образом, это может привести к тому, что несколько собственных потоков будут обслуживать один поток Java???
Ответ №1:
Я бы предположил, что это скорее вопрос nmon, чем Java, и чтобы решить его, я бы взглянул на top
команду, которая предоставляет информацию об использовании процессора для каждого процесса. Я предсказываю следующий результат: вы увидите, что один поток Java использует около 100% процессорного времени (что нормально, поскольку процентное соотношение между процессами в top относительно одного (виртуального) ядра), возможно, второй и третий потоки Java с гораздо меньшим использованием ЦП (потоки ввода-вывода). В зависимости от выбора gc вы можете даже обнаружить один или несколько gc-потоков, однако намного меньше 20.
Однако HotSpot не будет (и даже не может, насколько мне известно) самостоятельно распараллеливать последовательную задачу.
Комментарии:
1. Я проверил приложение с помощью «top -H», и там было много потоков, принадлежащих java. Затем я проверил приложение с помощью «jstack» во время выполнения и обнаружил там большое количество потоков gc: «Поток задач GC # 0» …. «Поток задач GC # 14» Итак, я считаю, что загрузка, показанная nmon, была сгенерирована потоками GC. Я прочитаю больше о том, как управлять GC. @Jonathan спасибо, что вернулся с идеей GC, у тебя есть мой голос
2. Я использовал -XX:ParallelGCThreads для управления количеством потоков и получил точно ожидаемые результаты в nmon — 4 потока приложений использовали 4 ядра. @Джонатан, еще раз спасибо!