Ответ 1
коллекция eden по-прежнему подвержена паузе STW, поэтому 20 мс могут быть совершенно нормальными в зависимости от поведения размещения и размера/размера кучи живого набора.
Наше приложение быстро считывает данные по сокетам TCP/IP в Java. Мы используем библиотеку NIO с неблокирующими сокетами и селектором, чтобы указать готовность к чтению. В среднем общее время обработки для считывания и обработки прочитанных данных составляет субмиллисекунду. Однако мы часто наблюдаем всплески в 10-20 миллисекунд. (работает в Linux).
Используя tcpdump, мы можем видеть разницу во времени между чтением tcpdump двух конфиденциальных сообщений и сравнить это с временем приложений. Мы видим, что tcpdump не задерживается, тогда как приложение может показывать 20 миллисекунд.
Мы уверены, что это не GC, потому что в журнале GC практически нет полного GC, а в JDK 6 (по тому, что я понимаю) GC по умолчанию параллелен, поэтому он не должен приостанавливать потоки приложения (если только не делать Полный GC).
Он выглядит почти так, как будто существует некоторая задержка для метода Java Selector.select(0)
, чтобы вернуть готовность к чтению, потому что на уровне TCP данные уже доступны для чтения (и tcpdump читает его).
Дополнительная информация: при пиковой нагрузке мы обрабатываем около 6000 x 150 байт за сообщение или около 900 МБ в секунду.
коллекция eden по-прежнему подвержена паузе STW, поэтому 20 мс могут быть совершенно нормальными в зависимости от поведения размещения и размера/размера кучи живого набора.
Является ли ваш Java-код запущенным под RTLinux или другим дистрибутивом с жесткой возможностью планирования в реальном времени? Если нет, 10-20 мс джиттера во время обработки кажется вполне разумным и ожидаемым.
У меня была такая же проблема в java-сервисе, над которым я работаю. При отправке одного запроса повторно от клиента сервер будет блокировать в том же месте в потоке в течение 25-35 мс. Отключение алгоритма Nagle в сокете исправил это для меня. Это можно сделать, вызвав setTcpNoDelay (true) на Socket. Это может привести к увеличению перегрузки сети, поскольку ACK теперь будут отправляться как отдельные пакеты. См. http://en.wikipedia.org/wiki/Nagle%27s_algorithm для получения дополнительной информации о алгоритме Нагле.
Из tcpdump faq:
КОГДА ВРЕМЯ ВЫКЛЮЧАЕТСЯ ПАКЕТ? КАК ТОЧНО - ВРЕМЕННЫЕ СТАМПЫ?
В большинстве ОС, на которых tcpdump и запуск libpcap, время пакета с печатью как часть процесса драйвер сетевого интерфейса или сетевой стек, обрабатывающий его. Это означает, что пакет не является временем с печатью в тот момент, когда он прибывает на сетевом интерфейсе; после пакет поступает в сеть интерфейса, будет задержка до прерывание доставляется или сетевого интерфейса (т.е. сетевой интерфейс может не прерываться хозяин немедленно - водитель может быть настроен для опроса интерфейса, если сетевой трафик тяжелый, чтобы уменьшить количество прерываний и процесс больше пакетов за прерывание), и там будет являться дополнительной задержкой между точка, с которой начинается прерывание обрабатывается, а отметка времени - генерируется.
Итак, вероятность того, что отметка времени сделана на уровне привилегированного ядра, а потерянные 20 мс - накладные расходы на контекст обратно в пространство пользователя и на Java и логику селектора сетей JVM. Без анализа системы в целом я не думаю, что можно сделать утвердительный выбор причины.