понедельник, 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'ы.

Home Portal

Домашний портал. Эта та страничка, что стоит в браузере как home page. Отсюда я/жена читаю новости, смотрю погоду за окном (графики влажности, температуры), наблюдаю за работой сервера и т.д. Предназначен он для home automation (ну там энергосберегающий умный дом (smarthouse) и т.д.). Работа в свободное время. Сбор информации и управление 1-wire, в будущем будет еще X-10 (управление светом), камеры и т.д.. Много всего написано, но на сервере на production сервере еще не выложено. Сам портал напроч AJAX'ный, перегрузок страниц не требует. В качестве платформы Jboss Portal + DOJO (следующие портлеты будут без dojo, но на GWT). В качестве ядра, standalone java process со стеком spring + termware + quartz и т.д.

Но вообще пост не об этом, а о двух подряд идущих анонсах в ленте torrent.net.ua (см. скриншоты).

Картинка 1
Картинка 2
Картинка 3

четверг, 10 июля 2008 г.

Выбор domain языка

Предположим нужно контроллировать некоторую автоматику. Для этих целей необходимо выбрать способ формализации алгоритмов управления. Короче и проще говоря, нужен язык со следующими, как мне кажется, требованиями:
1. Имеющий реализацию интерпретатора на Java.
2. Парсинг исходного кода в runtime'е, а не предварительно.
3. Локоничный.
4. Расширяемый словарь.
5. Возможность захватывать состояние выполнения... мммм.. как это по-русски.. continuationы.

Это может быть что угодно, функциональный, императивный, декларативный, rewriting engine, macro и.д.

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

Loop:
T = GetCurrentTemperature
State = AccordingToMode ( If (T < REQUIRED_T, On, Off) )
SetDeviceState ("HeaterDevice", State)
WaitEvent (Polled("TemperatureDevice"), ModeChange)
При этом, в момент вызова WaitEvent выполнение скрипта должно прерваться с сохранением состояния, чтобы я дальше мог продолжить выполнение после WaitEvent. Как это предполагается использовать из Java (типа того):
Script script = Script.prepare (scriptSource);
ScriptYield yield = script.run ();
eventManager.addPendingScript (yield.getScriptState(), yield.getResult());

а где-то позже, может быть очередное:
ScriptYield yield = scriptState.continue ();

Я не много хочу? :)

Update: Groovy не поддерживает cont-ions, jpython из-за отступов не получится никуда встроить толком, jruby не поддерживает (fiber в виде нитей не канает)... ищем дальше

Update: По результатам подошел TermWare.

четверг, 26 июня 2008 г.

Linux 2

Ну вроде разобрался с проблемой зависания. Это определенно не дрова видюхи - без них в консоли все равно висло. Это не перегрев - в винде все ok. Четыре зависших попыток компиляции ядра 2.6.25.9 под ядром 2.6.25.8 показали, что проблема воспроизводима легко. Под 2.6.24 удалось собрать 2.6.25.9. Но собрать под 2.6.25.9 ради теста саму 2.6.25.9 не получилось - висла. Скачал 2.6.26-rc8. Тестовая сборка под этим ядром прошла нормально. Проблемы с протоколом Samba исчезли (интересно, что scp как работала нормально, так и работает). Вроде жизнь наладилась. Всем спасибо за советы.

Итого. 2.6.25.6, 2.6.25.7, 2.6.25.8, 2.6.25.9 - на моей машине (64 бита, AMD) оказались не рабочими.

вторник, 24 июня 2008 г.

Linux

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

Эпизодически, несколько раз в день система фризится напроч. Тоесть мышиный курсор не двигается, музыка не играет и т.д.
Если я в это время залогинен по VNC на зафризенную машину, то в момент этот, я могу максимум что сделать - запустить zsh и все. И то наверное потому, что он в кэш памяти сидит. Изображение прорисовывается по нажатию на кнопку. Например набрал su , но ничего не произошло. Нужно любую кнопку нажать, чтобы увидеть запрос на логин. Странное поведение. В логах ничего подозрительного нет. shutdown -r now не отрабатывает (программа вообще не похоже, что запускается).

Если копирую что-то по smb протоколу, то в файле только первые несколько кил нормальные, а дальше нули идут. Тоесть mp3 музыка играет пару сек и затыкается, если играть smb share'ы. При этом с другого компа доступ к томуже smb ресурсу работает без проблем и глюков. Если копируют mp3'ки мне на шару, то играет все нормально.
Даже не знаю что думать. Куллеры крутятся.. все как обычно. Винда на компе работает нормально, в т.ч. и Crysis. Ядро 2.6.25.(от 6 до 8). Никому ничего не напоминает?

пятница, 20 июня 2008 г.

Документация AspectJ

Если кто-то как и я документацию читает только по-необходимости, то так же как и я может попасть в ловушку при чтении доки на AspectJ. Например глядя на пример:

<include within="javax.*"/>
<include within="org.aspectj.*"/>

может показаться, что аспекты будут применены ко всему, что внутри javax.*, на самом деле это не так ибо, аспекты будут примены только к тем классам, что в javax ни больше ни меньше. Т.е. к классам внутри javax.security это не относится. А если учесть, что непосредственно в javax пакете вообще нет ни одного класса (или есть, но я по памяти не помню), то пример явно идиотский. Короче, должно там быть на самом деле "javax..*"...

вторник, 3 июня 2008 г.

GWT (1.5)

Очень странные ощущения. После возни с AJAX'овыми вещами с помощью JavaScript'а, писать клиентский код на Java просто сказка. Если скомпилировалось - значит заработает. Но компилируется не всегда - к этому надо просто привынуть. Например GWT.create принимает в качестве аргумента Class, но не тут-то было. Например код:
Class c = MyService.class; // или получено из аргумента
MyServiceAsync svc = GWT.create (c);
Прервет компиляцию с сообщением "Only class literals may be used as arguments to GWT.create()".

Подход к package structure, который вроде как strongly recomended, весьма странен с моей точки зрения. Ну сабпакаджи client и server весьма логичны, но вот сабпакадж public - сомнителен (в него предполагается ложить ресурсы как я понял(?)). Более того, client классы не могут зависить от server классов. Т.е. нельзя ложить интерфейс сервиса в package server - его нужно ложить в пакадж client, а в server'е должна лежать только имплементация этого сервиса. Получается по сути таже tier based архитектура, но только наоборот. В классической (ну той к которой я привык), клиентская часть знает о серверной, но не наоборот. А в GWT'ной модели, как раз наоборот получается: серверная часть пользуется классами из клиентской (наследует интефрейсы которые хочет видеть клиент). Собственно это при желании можно обойти сделав отдельный GWT-Module для какого-то отдельно пакаджа с общими классами.. но это ж делать надо и против recomended structure. Впрочем я с первого же дня забил на эту структуру и разложил все по своему - главное понимать, что делаешь и тогда все работает.

Сервисы-сервлеты в Module.gwt.xml не прописываю. Заюзал spring-mvc: прописал в web.xml его диспатчер, а в app context'е прописываю сами сервисы-контроллеры (для spring-mvc они контроллеры, а для gwt они сервлеты, а для клиента они сервисы). Получилось красиво весьма. Пока нравится.

По уровню boilerplate'ности напоминает EJB 2.1.