2016-06-20 5 views
1

Мы запускаем веб-приложение с java7 и tomcat7. В нашем приложении производительность понесла совершенно неожиданно. Среднее время отклика удвоилось, и в пиковые времена проблема даже ухудшилась.java deadlock ухудшает производительность

Мы распечатали дамп потока и нашли нить, сидящую в ожидании навсегда состояния. Мы сделали несколько дампов потоков, и состояние этой нити не изменилось.

"logback-66215" daemon prio=10 tid=0x00007f86f4115800 nid=0x3758 waiting on condition [0x00007f868d817000] 
    java.lang.Thread.State: WAITING (parking) 
     at sun.misc.Unsafe.park(Native Method) 
     - parking to wait for <0x00007f8ddf241fa8> (a java.util.concurrent.SynchronousQueue$TransferStack) 
     at java.util.concurrent.locks.LockSupport.park(LockSupport.java:186) 
     at java.util.concurrent.SynchronousQueue$TransferStack.awaitFulfill(SynchronousQueue.java:458) 
     at java.util.concurrent.SynchronousQueue$TransferStack.transfer(SynchronousQueue.java:359) 
     at java.util.concurrent.SynchronousQueue.take(SynchronousQueue.java:925) 
     at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1068) 
     at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1130) 
     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) 
     at java.lang.Thread.run(Thread.java:745) 

Ссылки в этой теме 0x00007f868d817000 и 0x00007f868d817000 не были найдены на свалке нити.

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

Мы запускаем его на сервере с 12 ядрами. Мы контролируем использование ЦП, но не видим всплесков. Когда в пиковой нагрузке из-за около 500 запросов/сек потребление ЦП увеличилось до 800%, но не увеличилось до 1200% (что является максимальным). Он просто прекратил увеличиваться, когда достиг 800%, а затем проблемы с производительностью были действительно плохими, конечно.

Я недостаточно разбираюсь в внутренности резьбы, CPU, прерываниях, чтобы полностью понять эту ситуацию. Я действительно хотел бы понять эту проблему на более глубоком уровне.

Теперь мой вопрос: может ли кто-нибудь объяснить мне, почему такой тупик вызывает столько проблем? Почему он не отображается в использовании ЦП, поэтому мы видим полностью загруженный CPU? Или это просто проблема переключения контекста?

ответ

0

Исправьте меня, если я ошибаюсь, но на основе дампа потока выше и наличия SynchronousQueue я бы предположил, что вы используете CachedThreadPoolExecutor (Executors.newCachedThreadPool()) для выполнения некоторых задач.

Таким образом, дамп был бы одним из кэшированных потоков, просто ожидая, что задание будет выставлено в threadpool. Здесь нет ничего плохого, это не тупик. В любом случае реальный тупик будет явно указан как таковой в дампе потока.

Что касается потребления ЦП, поток, помещенный в состояние WAITING, не потребляет никаких циклов процессора - он даже не запланирован для выполнения.

Итак, откуда возникла ваша проблема с производительностью?

Трудно сказать, но если бы я был вами, я бы избегал использования CachedThreadPool, так как он будет старательно создавать столько потоков, сколько необходимо для выполнения заданий, даже если это означает, что вы едите всю память своего сервера (каждый поток имеет зарезервированная память для своего стека, которая составляет не менее 100 тыс.) и ЦП (ваш планировщик сходит с ума, если слишком много потоков для управления).

Возможно, вы захотите вручную настроить ThreadPoolExecutor (в отличие от использования фабрик Executors.new*), чтобы иметь возможность выбирать максимальное количество потоков, размер и тип очереди и стратегию отсрочки в случае большой массы заданий приходит.

Смежные вопросы