Как мы боролись с проблемами производительности в «Redmine». Кто виноват и как помочь?


    Конечно, статья не совсем верно названа. В чистом Redmine особо больших проблем с производительностью нет. Но мы, в процессе разработки большого количества плагинов, эти проблемы с легкостью вносили.

    Поэтому, статья расскажет о том, как разобраться в чем причина медленной работы той или иной функции плагина Redmine и какие инструменты могут помочь в этом. Многие советы, естественно, могут касаться не только самого Redmine, но и Rails-приложений в целом.

    Симптом у проблем с производительностью всегда один – это разгневанный пользователь, кричащий, клянущий твое ПО и возможно тебя лично.



    Rack Mini Profiler

    Чаще всего проблемы с долгим открытием какой-нибудь странички связаны с SQL-запросами. Это могут быть просто долго исполняющиеся SQL-запросы или циклические запросы вызванные особенностями механизма Active Record в ROR. В любом случае, Rack Mini Profiler – это мегополезная вещь для анализа проблем производительности в Redmine.

    Rack Mini Profiler – это маленький gem, который устанавливается в пару команд и в режиме почти реального времени показывает, какие запросы выполнялись в процессе загрузки странички, и сколько ушло времени на каждый запрос. Для анализа проблем производительности, эта штука просто незаменимая.

    На ранних стадиях программирования на Rails у меня было стойкое ощущение того, что Ruby on Rails настолько продуманный фреймфорк, что, пользуясь Active record, я просто выбирал нужные мне данные, думая, что обо всем остальном позаботились разработчики фреймворка.

    В результате? я наплодил большую кучку циклических SQL-запросов. С ростом количества пользователей, некоторые странички стали открываться очень долго.

    Rack Mini Profiler позволяет очень быстро найти причину долгого открытия странички у конкретного пользователя. Вот как, например, это может выглядеть, если не добавить «includes» в «active record» — конструкцию.

    Общее количество SQL-запросов само по себе наводит на подозрение:



    Если посмотреть более подробную статистику, то можно понять, что при открытие странички генерируются циклические SQL-запросы и эту проблему нужно устранить.



    Даже после того, когда пришло более глубокое понимание Active record в Rails, периодически, циклические запросы пролазили на рабочий сервер. Поэтому мы решили, что тестировщик, проверяя задачу, в обязательном порядке должен анализировать информацию из Rack Mini Profiler на наличие долгих и циклических запросов.

    Плагин для Redmine — «RmPlus DevTools»

    Rack Mini Profiler по умолчанию включен в development-среде и выключен в production. Но часто бывает нужно проанализировать ситуацию с производительностью именно в production-среде и у конкретного пользователя, поэтому мы написали небольшой плагин для Redmine, который подключает Rack Mini Profiler в production-среду Redmine и позволяет подключать профилирование только для конкретного пользователя – Redmine Dev Tools.



    Также, этот плагин подключает джем Oink (про него расскажу немного позже) и дает возможность вести более удобную разработку плагинов для Redmine в development-среде: нет необходимости перезагружать web-сервер для того, что бы изменения в JS-файлах применялись на странице.

    «OINK»

    Oink это еще один суперполезный джем для анализа проблем с производительностью. Он очень помог, когда у нас на рабочем сервере стала утекать память. Один из процессов Rails по непонятным причинам выедал больше гигабайта оперативной памяти и вешал весь Remine.

    Как следствие: кучка звонков на телефон, мурашки по коже и легкое ощущение бессилия.

    Oink позволяет проанализировать, какие контроллеры и экшены Rails съедают память, задав пороговое значение. Эта статистика проливает свет на источник проблемы, после чего устранение источника проблемы становится более тривиальным.

    oink --threshold 50 /usr/share/srv-redmine/redmine-2.5/log/oink.log



    Как-то вот так! Надеюсь, моя статья будет полезной. Мне она бы очень пригодилась в свое время.
    Поделиться публикацией
    Комментарии 13
      +4
      Надеюсь, моя статья будет полезной.

      Ну а выводы то какие?
      Что в итоге было сделано?
      На сколько это подняло производительность?

      Сейчас эта статья больше о полезных для разработчика плагинах, а не о «проблемах производительности».

      эту проблему нужно устранить

      Не нужно, ну или по крайней мере не сразу. Подобные запросы очень быстро выполняются (главное чтобы индекс по этому полю был), поэтому не факт что после переписывания станет заметно быстрее (=> каждый случай надо индивидуально смотреть).

      Кстати, если посмотреть вашу таблицу с кол-во запросов, то получаем что:
      317 запросов: 180мс (~0.57 мс/запрос)
       17 запросов: 108мс (~6.35 мс/запрос)
       13 запросов: 4.5мс (~0.35 мс/запрос)
      

      по-моему, очевидно, что затык не только в количестве.

      Кстати, авторы redmine очень любят использовать чрезвычайно медленные в mysql запросы вида WHERE IN(SELECT) — в первую очень я бы обратил внимание на них (используются, например, при поиске по полям).
        0
        Сейчас эта статья больше о полезных для разработчика плагинах, а не о «проблемах производительности».

        Да возможно заголовок не совсем корректно отражает суть статьи.

        Что в итоге было сделано?

        В итоге переписали кучу Active Record запросов. Кое где странички которые открывались по 5-10 секунд, стали открываться за 2. Проблемы с утечкой памяти были тоже в SQL-запросе, который тоже был переписан. Сейчас с производительностью все не плохо.

        Кстати, если посмотреть вашу таблицу с кол-во запросов, то получаем что:

        Это данные с девелоперской машины. На рабочей разница между двумя SQL-запросами и 300-ми циклическими видна на глаз.
          0
          Напишите пожалуйста о всех ваших изменениях, чего таить?
            0
            Напишите пожалуйста о всех ваших изменениях, чего таить?


            Не совсем понял вопрос. Можете конкретизировать?
            +2
            Отправьте Ваши патчи в сам Redmine
              0
              К сожалению многие хорошие патчи в redmine не попадают в ядро. Либо попадают слишком долго.
            0
            В кучку полезны gem'ов для отладки в особенности SQL запросов добавлю свои 5 копеек:

            Bullet — github.com/flyerhzm/bullet как раз поможет найти N+1 запрос
            Rails Panel + Meta Request — github.com/dejan/rails_panel удобно покажут это в закладках dev панели Chrome
              0
              А сколько у вас задач в Redmine сейчас создано? У нас 1.5кк и есть в некоторых местах серьезные проблемы по производительности. Несколько ускорили работу десятком индексов. Хорошо хоть пользователей всего 200 с копейками, а то сервак валился бы на раз-два-три.

              >> В итоге переписали кучу Active Record запросов

              А где вы их переписываете? Прямо в основном коде или есть возможность это как-то вынести в плагин? Потом проблем с обновлениями не испытываете?
                0
                А сколько у вас задач в Redmine сейчас создано? У нас 1.5кк и есть в некоторых местах серьезные проблемы по производительности. Несколько ускорили работу десятком индексов. Хорошо хоть пользователей всего 200 с копейками, а то сервак валился бы на раз-два-три.


                У нас 21660 задач.
                Пользователей около 500 но не все активные.
                В коробочном Redmine могут быть большие проблемы если иерархичность задач большую сделать. Там циклических запросов при апдейтах тогда хватает. Но мы принципиально не используем деревья из задач. Они нам не нужны совсем! Только для дерева целей (для управление компанией по целям).

                А где вы их переписываете? Прямо в основном коде или есть возможность это как-то вынести в плагин?


                Нет основной код мы никогда не трогаем только в плагинах. Речь в статье идет в основном о своих плагинах.

                Потом проблем с обновлениями не испытываете?


                Это когда как. Если правильно писать, то часто переход с одной версии redmine на другую проходит прозрачно. Но не всегда!
                  0
                  Redmine еще актуален? Читал, что большая часть команды ушла в форк ChiliProject.
                    0
                    ChiliProject похоже мертв (последняя версия около года назад выпущена, репозиторий на гитхабе тоже около года не обновлялся)
                      0
                      Действительно. Англоязычная википедия:

                      As of 2014, the ChiliProject fork is generally considered to be a zombie project, as only security updates have occurred in the last year. Moreover, the leader of the fork moved on from ChiliProject development in 2012. Finally, the last activity on the ChiliProject Devel list was July 2013, and the most recent commit was August 2013.
                      +2
                      На мой взгляд Redmine более чем актуален.

                    Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                    Самое читаемое