Использование ЦП на Java должно быть 100%... но это не

Я запускаю Java-программу на моем ноутбуке Core i7, у которого есть 8 ядер (4 физических, 4 HT). Программа использует 8 параллельных потоков и поэтому должна использовать весь процессор. При работе с параметром "-сервер" все равно 100%. Без него он составляет около 50% -60% в целом (всегда меняется с пиками на 100% и падает до 30%). Вот то, что я нахожу странным: когда я запускаю программу в отладке и ждут момента, когда загрузка процессора особенно низкая (30%), а затем приостановить выполнение, чтобы посмотреть, что делают восемь потоков, ни один из них не находится в состоянии блокировки, Кроме того, синхронизация между ними практически отсутствует. Вот что мне интересно:

  • В чем разница между клиентской и серверной VM, которая бы не позволяла процессору достигать 100% на клиенте?
  • В отсутствие синхронизации, что могло бы поддерживать поток от полного использования ядра? (возможно, связано с 1)

Изменить: вот мысль: код выделяет большие массивы и довольно быстро их переносит в GC. Неисправна ли нить при вызове "new SomethingBig()" и выделение этой памяти занимает время? Если в распределении обработки виртуальной машины есть один процесс для пула потоков, я думаю, это могло бы объяснить, почему они, кажется, делают паузу наугад, вне блоков синхронизации...

Edit2: Я уверен, что это вызвано GC сейчас. CPU снова достигает 100%, если я даю VM 1500Mb вместо 500Mb по умолчанию. Я думаю, что замедление не происходит в режиме сервера, потому что по умолчанию используется больше памяти.

Ответ 1

Если вы хотите отслеживать, что делают потоки Java, вы не должны запускать приложение в режиме отладки и приостанавливать его.

Скорее, вы должны собрать дампы потоков с помощью kill -3 <pid> в определенный промежуток времени, когда загрузка процессора падает.

В связи с вашим вторым обновлением вы должны включить GC-протоколирование с отметками времени и скорректировать снижение замедленности/использования ЦП со временем коллекции Young/Full GC.

Ответ 2

Не относится к Java конкретно, но количество потоков, которое у вас есть, должно быть больше, чем количество ядер, которые вы должны наилучшим образом использовать в своем процессоре, потому что существует много раз, когда конкретный поток не может выполнить, поскольку так как более очевидное ожидание переменной условия, удерживаемой другим потоком, потоки могут быть блокированы по другим причинам, также как и промашка в кеше, может потребовать, чтобы поток ожидал, будут ли данные загружены в кеш-память cpus, ему, возможно, придется ждать ввода от некоторый источник, который медленнее, чем процессор, виртуальный пейджинг может привести к тому, что ваш поток будет ждать. Если у вас больше потоков, чем у вас есть ядро, когда один поток блокируется по какой-либо причине, другой может использовать это ядро, которое освобождается. Хорошее начальное значение составляет около 1,5 X количество ядер, которые у вас есть.