Увеличение потребления памяти пассажиром Phusion с 1.9.3 (system) до 2.1.2 (RVM) в Ubuntu

#ruby-on-rails #ubuntu #rvm #passenger

#ruby-on-rails #ubuntu #rvm #пассажир

Вопрос:

У меня система Ubuntu с 512 МБ физической оперативной памяти и 512 МБ подкачки. Запуск моих четырех приложений Rails 3.2.12 на сервере Passenger 4.0.45 (модуль Apache) с использованием однопользовательской (моей пользовательской) RVM Ruby 2.1.2 потребляет примерно на 30% больше памяти, чем при настройке Passenger на использование более старой системы (root) Ruby 1.9.3. Это единственное отличие в конфигурации Passenger.

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

Я не могу понять, почему использование RVM заставляет пассажира использовать больше памяти. Я сомневаюсь, что это из-за Ruby 2.1.2, если только нет параметров памяти, которые мне нужно настроить.

Ответ №1:

Стандартные настройки для ruby 2.1.2 увеличивают использование памяти по сравнению с 2.0.0 (который, я полагаю, был на одном уровне с 1.9.3, если не учитывать улучшения копирования при записи в 2.0.0)

Причина в том, что в Ruby 2.1 введен новый алгоритм сборки мусора. В двух словах алгоритм предполагает, что, хотя некоторые объекты живут долго (например, объекты, представляющие ваш код), другие живут очень недолго. Старые ruby потратили бы много времени, пытаясь определить, все ли объекты готовы к сборке мусора, в то время как ruby 2.1 переключается между второстепенными коллекциями (попробуйте собрать только недолговечные объекты) и основными коллекциями (попробуйте собрать долгоживущие).).

Это повышает производительность (небольшие коллекции выполняются намного быстрее) за счет некоторого использования памяти.

Вы можете настроить это, используя (среди прочего) RUBY_GC_HEAP_OLDOBJECT_LIMIT_FACTOR переменную среды. Значение по умолчанию равно 2, значение 0.9 отключает сборщик мусора поколений, а промежуточные числа уменьшают объем памяти в пользу производительности.

Вы также можете использовать библиотеку jemalloc (в любой версии ruby), чтобы немного повысить производительность и немного уменьшить использование памяти.

Наконец, часть проблемы с приложениями rails заключается в том, что многие приложения имеют то, что можно было бы назвать средне-живыми объектами, которых хватает на весь запрос — попытка Ruby разделить объекты всего на 2 поколения не совсем достаточна. Планируется, что Ruby 2.2 улучшит это.

У Сэма Саффрона есть отличный пост по этому поводу, если вы хотите прочитать больше

Кроме того, ruby 2.1.3 внес некоторые изменения в синхронизацию gc, что в большинстве случаев сокращает использование памяти по сравнению с 2.1.2

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

1. Спасибо. Я могу подтвердить, что установка RUBY_GC_HEAP_OLDOBJECT_LIMIT_FACTOR = 0.9 устраняет это «раздувание» памяти, что по иронии судьбы приводит к повышению производительности, учитывая мою ограниченную память (я должен ограничить Passenger 1 процессом на приложение). Есть идеи, как внедрить jemalloc в мой процесс Apache / Passenger / Ruby? В настоящее время я запускаю службу с помощью apachectl.

2. На самом деле, это не удаляет его полностью, но возвращает потребление памяти чуть выше 1.9.3 и остается более стабильным при доступе к различным приложениям. Это разница примерно в 200 МБ, что составляет примерно четверть моей общей виртуальной памяти. Похоже, что Passenger агрессивно заменяет память неактивного приложения на файл подкачки, чем полнее становится файл подкачки.

3. Я использую jemalloc, устанавливая LIBS =-ljemalloc при компиляции ruby. Вы должны быть в состоянии сделать это с помощью переменной окружения LD_PRELOAD, но я этого не сделал.