понедельник, 11 августа 2008 г.

Зедаржки в Java

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

1. Пускать приложение с schedtool -n -20 -R -p 1 -e /opt/mywire/bin/mywire
Данная команда позволяет запустить приложение в realtime группе с приоритетом 1. Все приложение linux имеют приоритет 0 независимо от nice level'а. Таким образом работа нашего mywire всегда приоритетнее любой задачи.

2. В некоторых критичных нитях, с помощью обращения к native методу происходит установка приоритета в значение 40. Таким образом внутри самого приложения нити имеют разные приоритеты. Это опасно и может привести к блокировкам!

3. Для того, чтобы ни в коем случае mywire не оказался в свопе, память лочится с помощью обращения к native методу mlockall.

4. Сам java процесс пускается со следующими опциями:

-Xms30m -Xmx64m -XX:PermSize=15m -XX:MaxPermSize=30m
-XX:+UseTLAB -jvm server
-XX:MaxGCPauseMillis=20 -XX:+UseConcMarkSweepGC -XX:+CMSIncrementalMode
-XX:+CMSClassUnloadingEnabled
-XX:+ExplicitGCInvokesConcurrentAndUnloadsClasses
-XX:+BackgroundCompilation

Количество памяти, которое я отдаю под heap выбранно таким образом, чтобы сразу после сборки мусора (full gc), свободной памяти было где-то 60%.

Надеюсь ничего не забыл. Как результат мы имеем задержки порядки 10-16мс. При том, что библиотека quartz сама работает с дискретеностью в 10мс. Тоесть если ей сказать, что таску нужно запустить через 5мс, она ее все равно запустить через 10.

К сожалению раз в час происходит full gc или что-то типа того и это влечет за собой неожиданные задержки. Величина зависит от того, как совпадут время срабатывания и начало сборки мусора. В среднем это 200мс. Бывает и 500мс и 700мс. Будем думать как это побороть.

Вот графики:
Latency:


Память.


Видно, что в момент сборки мусора был всплеск задержек.

Предугадывая вопросы:
Java - чтобы писать быстрее.

Latency - в данном случае, это разница времени момента срабатывания таймера и времени, в которое данный таймер должен был сработать. Тоесть, например, если было сказано спать 100мс, а таймер проспал 120мс, то задержка 20мс.

Важность Latency заключается в том, что опрашивать некоторые датчики необходимо весьма часто, скажем датчик движения 2 раза в секунду. В моем варианте датчик движения замыкает размыкает контакты конденсатора давая ему зарядится, таким образом датчик напряжения 1-wire успеет заметить какой-нибудь заряд, даже если он пропустит сам импульс. Так вот если Latency будет слишком высокой (скажем 2-3 секунды), то срабатывания датчик может просто остаться незамеченным.

Кто озадачился вопросом, почему датчик движения не может сам сообщить о срабатывании, отвечу: 1-wire сеть может иметь только одного master'а, все остальные slave'ы.

Комментариев нет:

Отправить комментарий