Загрузка многоядерного процессора приложением Java - PullRequest
2 голосов
/ 12 октября 2011

У меня есть программа, которая сортирует большие файлы, разбивая их на куски, сортируя куски и объединяя их в окончательный отсортированный файл. Приложение запускает один поток для загрузки / сохранения данных из / в файл - только один поток выполняет операции ввода-вывода. Также есть еще два потока, которые получают данные чанка, сортируют их и затем отправляют отсортированные данные обратно в поток, который выполняет ввод / вывод.

Таким образом, в целом работают 4 потока - основной поток, поток, который загружает / сохраняет данные, и два потока, которые сортируют данные.

Я думал, что во время выполнения я увижу 1 спящий поток (основной), который не требует времени ЦП, и 3 активных потока, которые используют 1 ядро ​​ЦП каждый.

Когда я запускаю эту программу на двухъядерном 6-ядерном процессоре с гиперпоточностью (24 процессора), я вижу, что ВСЕ 24 процессора загружены на 100%!

Первоначально я думал, что алгоритм сортировки является многопоточным, но после изучения источников Java я обнаружил, что это не так.

Я использую простой Collections.sort (LinkedList) для сортировки данных ...

вот некоторые подробности:

# java -version
java version "1.6.0_26"
Java(TM) SE Runtime Environment (build 1.6.0_26-b03)
Java HotSpot(TM) 64-Bit Server VM (build 20.1-b02, mixed mode)

# uname -a
Linux 2.6.32-28-server #55-Ubuntu SMP Mon Jan 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");
    }
}

[UPDATE]
Вот снимок экрана, который я сделал при запуске программы выше (использовал nmon): http://imageshack.us/photo/my-images/716/cpuload.png/

1 Ответ

1 голос
/ 13 октября 2011

Я бы предположил, что это скорее вопрос nmon, чем java, и для его решения я бы взглянул на команду top, которая предоставляет информацию об использовании ЦП для каждого процесса. Я прогнозирую следующий результат: вы увидите один поток Java, использующий почти 100% процессорного времени (что нормально, так как процентная доля процессов наверху относительно одного (виртуального) ядра), возможно, второй и третий поток Java с большим меньшее использование процессора (потоки ввода / вывода). В зависимости от выбора gc вы можете даже обнаружить один или несколько gc-потоков, но гораздо меньше 20.

Однако HotSpot не будет (и даже не может, насколько мне известно) распараллеливать последовательную задачу самостоятельно.

...