06 February, 2010

Список для проверки при оптимизации Grails приложений

Выкладываю ниже список задач, которые нужно/можно выполнить для оптимизации приложения, написанного на Grails, может кому пригодится.

Тестирование проведённых оптимизаций

Первым делом необходимо разработать критерии проверки, которые позволят оценить эффективность проведённых оптимизаций.
  1. Установить Java Melody плагин для Grails для проведения анализа.
  2. Разработать скрипты для проведения нагрузочного тестирования.
  3. Прогнать скрипты.
  4. Проанализировать результаты Java Melody, выявить узкие места, произвести нужные оптимизации.

Общие оптимизации

Очень часто обновление до последней версии используемых библиотек попутно улучшает производительность.
  1. Обновить Java до последней версии
  2. Обновить Groovy до последней версии.
  3. Обновить Grails до последней версии.
  4. Обновить jQuery до последней версии.
  5. Оптимизировать настройки виртуальной машины Java (например, -server -Xmx270m -Xms270m -XX:MaxPermSize=80m -Xverify:none -XX:+UseParallelGC -XX:+UseParallelOldGC -XX:+UseAdaptiveSizePolicy -XX:SurvivorRatio=4 -XX:TargetSurvivorRatio=90 -XX:MaxTenuringThreshold=31 -XX:+AggressiveOpts)
    a. http://java.sun.com/javase/technologies/hotspot/gc/gc_tuning_6.html
    Вообще, по оптимизации JVM написаны целые книги, так что не буду здесь останавливаться.

Оптимизация клиентской части

  1. Настроить кэширование статических ресурсов в Томкате.
  2. Настроить сжатие статических ресурсов в Томкате.
  3. (поставить прокси на nginx для кэширования статических ресурсов ?)
  4. Установить плагины для Firebug, которые оценят производительность клиентской части.
  5. Проанализировать страницы веб-сайта с их помощью
  6. Провести предлагаемые оптимизации.

Оптимизация клиентской части приложений, написанных на Grails

  1. Установить плагин UI Performance
  2. Провести оптимизацию с использованием плагина UI Performance

Оптимизация базы данных

  1. Оптимизировать производительность сервера базы данных (SQL Server)
    a. http://www.sql-server-performance.com/tips/all_main.aspx
    a. http://msdn.microsoft.com/en-us/library/ms998577.aspx
  2. Проверить наличие индексов в базе данных, добавить необходимые
  3. Найти неоптимальные запросы в БД, оптимизировать

Оптимизация работы с базой данных

  1. Обновить версию JDBC-драйвера
  2. Настроить кэширование в Hibernate.
    Ресурсов в сети предостаточно, навскидку вот парочка.

Оптимизация серверной части приложения

  1. Произвести профилирование приложения (использовать Visual VM, YJP Profiler), найти узкие места и оптимизировать их.

Оптимизация серверной части приложения (опционально)

  1. Установить плагин Perf4J для грэйлза
  2. Добавить необходимые счётчики в код
  3. Прогнать нагрузочные тесты, найти узкие места, оптимизировать.

Заключение

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

04 February, 2010

Вложенные транзакции в базах данных

Summary: Некоторые особенности вложенных транзакций.

Иногда бывает так, что при обработке запроса необходимо открыть ещё одну транзакцию в рамках текущей транзакции. Это называется вложенной транзакцией.

Очень многие базы данных не поддерживают вложенные транзакции вообще, например, MySQL и Oracle. А те, что поддерживают, делают это на минимальном уровне, например, Sybase поддерживает только псевдовложенные транзакции.

Вложенные транзакции могут быть следующих видов:

  1. Псевдо-вложенные транзакции
  2. Вложенная субтранзакция
  3. Вложенная независимая транзакция

Псевдовложенные транзакции


Этот тип транзакций поддерживается базой данных Sybase.
Псевдо-вложенные транзакции позволяют использовать транзакции одна внутри другой, при этом не реализуя механизм вложенных транзакций. Суть состоит в том, что имеется счётчик уровня вложенности транзакций, который увеличивается на 1 при каждом вызове BEGIN TRANSACTION и уменьшается на 1 при каждом вызове COMMIT. Когда счётчик становится равным 0 происходит коммит всех произведённых изменений.

Если во время проведения транзакции происходит ошибка, то вызывается ROLLBACK, но здесь есть загвоздка - что делать с последующими вызовами BEGIN TRANSACTION и COMMIT. Оптимальным решением является кидание исключения, но это необходимо отслеживать и учитывать на стадии проектирования и реализации, чтобы не возникло неприятных ситуаций при эксплуатации.

Псевдовложенные транзакции являются самым простым способом реализации вложенных транзакций.

Пример псевдотранзакции для базы данных Sybase:
begin tran
    select @@trancount
    /* @@trancount = 1 */
    begin tran
        select @@trancount
        /* @@trancount = 2 */
        begin tran
            select @@trancount
            /* @@trancount = 3 */
        commit tran
    commit tran
commit tran
select @@trancount
/* @@ trancount = 0 */

Вложенная субтранзакция


Данный вид вложенных транзакций решает проблему с обработкой ошибок при ROLLBACK.
При коммите вложенной транзакции происходит коммит, но он не обладает свойством Durability - окончательный результат зависит от результата внешней транзакции - если внешняя транзакция заканчивается успешно, то и результат внутренней транзакции также фиксируется. Если же при фиксации изменений внешней транзакции происходит ошибка, то внутренняя транзакция также откатывается. Кроме того, необходимо обратить внимание на то, что если внутренняя транзакция заканчивается неуспешно, то внешняя транзакция может закончиться успешно, если не выкинуть исключение наружу. Таким образом, для данного вида вложенных транзакций необходимо выкидывать исключение наружу, для того, чтобы прервать и откатить внешнюю транзакцию в случае ошибки.

Вложенная независимая транзакция

Особенность данного вида вложенных транзакций заключается в том, что после создания вложенной транзакции она является полностью независимой от транзакции, внутри которой она была создана. Её результаты фиксируются и откатываются независимо от внешней транзакции.

Вложенные транзакции и принципы ACID

Вложенные транзакции выглядят достаточно подозрительными в том смысле, что они могут нарушать принципы ACID:
1. Вложенная субтранзакция может нарушать принцип Durability, так как уже зафиксированные изменения могут откатиться в случае отката внешней транзакции.
2. Вложенная независимая транзакция может нарушать принципы Atomicity и Consistency при возникновении ошибок во внешней или вложенной транзакции.

Подробнее о принципах ACID можно прочитать в этом посте.

Заключение

Я считаю, что следует избегать ситуаций, когда нужны вложенные транзакции. Кроме того, спецификация Java EE не поддерживает вложенные транзакции.