Мы диагностируем проблемы с производительностью Ruby на наших серверах приложений, которые нам удалось свести к простому тесту.
Мы сравниваем производительность машины в нашем кластере разработки с машиной в нашем производственном центре обработки данных.
Мы использовали этот простой Ruby oneliner:
5000000.times { a = []; a << 1; a.length }
И мы отметили, что он постоянно на 55% медленнее на производственной машине.
Очевидно, что это могло быть и почему мы думаем, что это не так:
Почему мы не думаем, что это нагрузка или оборудование?
Во-первых, у них похожие нагрузки и конфигурации оборудования. Во-вторых, мы написали тестовый скрипт на Python:
n = 10000000
while n > 1:
n = n - 1
a = []
a.append(4)
len(a)
а это стабильно 10% Быстрее на производстве, чем на разработке, чего мы и ожидали. Если проблема была в загрузке или оборудовании, разве Python не работал бы медленнее и в производственной среде?
Вкратце обе машины виртуализированы с помощью ESXi.
Виртуальная машина разработки имеет 4 ГБ ОЗУ и размещается на машине с двухъядерным четырехъядерным процессором AMD Opteron 2376 @ 2,294 ГГц, 32 ГБ, обеспечивая одно виртуальное ядро для виртуальной машины.
производственная виртуальная машина имеет 4 ГБ ОЗУ и размещена на машине с двухъядерным четырехъядерным процессором AMD Opteron 2354 @ 2,211 ГГц, 32 ГБ, обеспечивая четыре виртуальных ядра для виртуальной машины (обновление: теперь мы пробовали использовать одно виртуальное ядро на всех виртуальных машинах, и это не имело никакого значения)
Операционная система - Ubuntu Hardy 64bit. Наш интерпретатор Ruby:
ruby 1.8.6 (2008-08-11 patchlevel 287) [x86_64-linux]
и наш интерпретатор Python
Python 2.5.2 (r252:60911, Jul 31 2008, 17:31:22)
NB. Мы также пробовали это с Ruby Enterprise Edition, и результаты такие же.
Вы пробовали УМЕНЬШИТЬ количество виртуальных ЦП, которые вы передаете рабочей виртуальной машине?
Я знаю, что это звучит контрпродуктивно, но, и вы, возможно, уже знаете об этом, ESX не предоставит виртуальной машине НИКАКОГО процессорного времени, если ВСЕ слоты виртуальных ЦП, выделенные какой-либо виртуальной машине, не являются свободными, т.е. если виртуальной машине назначено 4 виртуальных ЦП. к нему, и они просто не все бесплатны, тогда виртуальная машина вообще не получает времени. Я знаю, что это звучит ментально, но серьезно попробуйте перейти на 2 или 1 виртуальный ЦП и запустить его снова.
Удачи.
Я понятия не имею, что происходит, но я подумал, что поделюсь парой других аппаратных различий, основанных на процессорах, посмотрю, поможет ли это кому-то еще приблизиться к ответу.
Я немного устарел с оборудованием, но я предполагаю, что это означает, что доступ к памяти в целом значительно быстрее на машине разработки? Итак, если Ruby каким-то образом был более «требователен к памяти» (и я действительно не понимаю, что я имею в виду!), То это могло бы проявиться как большая разница в производительности?
(Я искал, есть ли в новом процессоре какая-нибудь функция виртуализации, которая могла бы объяснить разницу, но ничего не вышло.)
Пара вопросов ...
На самом деле я тоже думал об этом проспекте. Поскольку на производственном сервере кеш меньше, он исчерпает его быстрее, и ему придется прибегать к использованию основной памяти. Если в производственной среде этот доступ осуществляется медленнее, чем при разработке, это может быть причиной проблемы.
Однако такая же проблема может или должна произойти и с Python. Поскольку и Ruby, и Python реализованы на C, целочисленный размер, вероятно, будет одинаковым (хотя это предположение может быть неверным).
Короче еще ищу!
Вопрос: как вы проводите бенчмаркинг? Используете ли вы тест Ruby для версии Ruby или какой-либо внешний инструмент? Если первое, мне интересно, является ли что-то в библиотеке тестов, что вызывает проблему.
На прошлой неделе у меня была аналогичная проблема в нашей системе. Оказалось, это потому, что кто-то установил / потребовал activesupport, который изменял кучу вещей в нашем стеке классов, вызывая замедление. Это было обнаружено только при работе против реального трафика. Проверьте установленные гемы на медленной системе и сравните версии с машиной разработки. Возможно, что-то не в порядке.
Я обычно не доверяю производительности VMWare, поэтому мне было бы очень интересно посмотреть, что бы произошло, если бы они были одинаковыми конфигурациями vmware.
Эээ ... просто чтобы убедиться, что происходит, когда вы делаете:
n = 1000000
while n > 1 do
n = n - 1
a = []
a.push 4
a.length
end
Я знаю, что это функционально эквивалентно 1000000.times { a = []; a << 4; a.length }
, но функция times может делать что-то необычное за кулисами? Я также согласен с утверждением о многопоточности, но это фактически означает, что блок разработчика всего на 0,083 ГГц быстрее, что вряд ли объясняет падение на 55%. Было бы интересно посмотреть, что делает Ruby 1.9, но если вы пробовали REE, я сомневаюсь, что разница в производительности будет слишком большой. Я предполагаю, что это точно такая же скорость диска, кешей памяти и т. Д.?
Это потому, что Ruby не может воспользоваться дополнительными виртуальными ядрами из-за того, что он использует зеленые потоки, в то время как python с нативными потоками может? (Здесь дикая задница догадывается - я действительно не понимаю, о чем говорю).