Немного из жизни, или Как мы Java в OracleDB бороли.
Так как мы ничего не боимся, в т.ч. нестандартных решений, а смотрим на всё открытыми глазами, то и в одной из задач закачку данных в БД из веб-сервиса сделали в лоб — на java написан клиент, который установлен в БД, и прикидывается PL/SQL пакетом. Таким образом, исключется лишний траффик на сервер приложений и потом в БД.
Если бы могли договориться с DBA сделать по-другому, поставив процесс java рядом с БД и настроив memshared-транспорт, так бы и поступили, но не вышло.
В общем, решение заработало. Стали выполнять тесты, и оказалось, что на мощном сервере это работает медленнее, чем на дохлом рабочем ноутбуке, а ещё и падает иногда с out of memory!
У руководителей проекта началась лёгкая паника, конечно же, а разработчики принялись храбро выдвигать гипотезы одну за одной:
- мало памяти
- GC тормозит
- JIT плохой
- стык с PL/SQL тормозит
- фаза луны мешает.
Но спасает, как всегда, чтение документации вслух. А конкретно, в Oracle используется Java-6 совместимая JVM (Aurora или JServer). Среди всяких интересных вещей там описана одна нужная: потоки в JServer реализованы по методу невытесняющей многозадачности. Т.е. если вы запускаете несколько потоков, выполняться они будут последовательно. Ну а наши гонщики за high performance, конечно же, сделали в java потоки, фьючерсы, всё очень асинхронно и "быстро".
Полечилось переписыванием на самый тупой последовательный вариант, а параллелизация была перенесена на уровень PL/SQL несколькими сессиями. Заработало в итоге 3-4 раза быстрее, чем если качать данные через dblink, на что и был исходный расчёт.
Тут и сказочке конец бы пришёл, да стало интересно, а как это в CLR, который в SQL ставится. Принялись смотреть, и удивились: оказывается, там поверх невытесняющей многозадачности реализована своя вытесняющая!
А конкретно, в разных "safepoint" (запуск gc, i/o, обращения в БД другие) исполнение переключается на другой поток. Гипотеза используется следующая: не может ведь поток работать и gc не вызываться. А если такое происходит (числодробилка), то диспетчер потоков этот факт отмечает, и следующий раз такой жадный до CPU поток свой квант получит позднее, или вообще будет пропущен.
Так как мы ничего не боимся, в т.ч. нестандартных решений, а смотрим на всё открытыми глазами, то и в одной из задач закачку данных в БД из веб-сервиса сделали в лоб — на java написан клиент, который установлен в БД, и прикидывается PL/SQL пакетом. Таким образом, исключется лишний траффик на сервер приложений и потом в БД.
Если бы могли договориться с DBA сделать по-другому, поставив процесс java рядом с БД и настроив memshared-транспорт, так бы и поступили, но не вышло.
В общем, решение заработало. Стали выполнять тесты, и оказалось, что на мощном сервере это работает медленнее, чем на дохлом рабочем ноутбуке, а ещё и падает иногда с out of memory!
У руководителей проекта началась лёгкая паника, конечно же, а разработчики принялись храбро выдвигать гипотезы одну за одной:
- мало памяти
- GC тормозит
- JIT плохой
- стык с PL/SQL тормозит
- фаза луны мешает.
Но спасает, как всегда, чтение документации вслух. А конкретно, в Oracle используется Java-6 совместимая JVM (Aurora или JServer). Среди всяких интересных вещей там описана одна нужная: потоки в JServer реализованы по методу невытесняющей многозадачности. Т.е. если вы запускаете несколько потоков, выполняться они будут последовательно. Ну а наши гонщики за high performance, конечно же, сделали в java потоки, фьючерсы, всё очень асинхронно и "быстро".
Полечилось переписыванием на самый тупой последовательный вариант, а параллелизация была перенесена на уровень PL/SQL несколькими сессиями. Заработало в итоге 3-4 раза быстрее, чем если качать данные через dblink, на что и был исходный расчёт.
Тут и сказочке конец бы пришёл, да стало интересно, а как это в CLR, который в SQL ставится. Принялись смотреть, и удивились: оказывается, там поверх невытесняющей многозадачности реализована своя вытесняющая!
А конкретно, в разных "safepoint" (запуск gc, i/o, обращения в БД другие) исполнение переключается на другой поток. Гипотеза используется следующая: не может ведь поток работать и gc не вызываться. А если такое происходит (числодробилка), то диспетчер потоков этот факт отмечает, и следующий раз такой жадный до CPU поток свой квант получит позднее, или вообще будет пропущен.