Ruby на вашем сервере может работать в 2 раза медленее из-за RVM


    Просматривая сегодня «Ruby Inside», наткнулся на статью Justin Kulesza Is Your Application Running with Ruby – Slow?. Статья от 6 ноября, но на Хабре об этой ситуации ни слова. А суть статьи вот в чем: ребята переносили свое приложение с сервера на Solaris на сервер с Ubuntu и использовали RVM для компиляции Ruby. Однако после переноса они заметили, что приложение стало как-будто бы тормознутее. Сначала погрешили на железо, но быстро выяснили, что дело в RVM, а именно в том, что RVM совершенно не использует оптимизацию при компиляции.

    Диагностика проблемы очень простая:
    $ time ruby -e "count = 0; while(count < 100000000); count = count + 1; end; puts count"                                                                                                         
    100000000
    
    real    0m9.019s
    user    0m8.933s
    sys     0m0.016s
    

    «Нормальное» время выполнения должно быть не выше ~4 секунд.

    Плюс отсутствие флагов оптимизации в ~/.rvm/log/your.ruby.version/make.log:
    CC = gcc
    LD = ld
    LDSHARED = gcc -shared
    CFLAGS = -I/home/user/.rvm/usr/include -fPIC
    XCFLAGS = -include ruby/config.h -include ruby/missing.h -fvisibility=hidden -DRUBY_EXPORT
    CPPFLAGS =   -I. -I.ext/include/x86_64-linux -I./include -I.
    DLDFLAGS = -Wl,-soname,libruby.so.1.9
    SOLIBS = -lpthread -lrt -ldl -lcrypt -lm
    

    В CFLAGS должно присутствовать -O3.

    Проверил на своем сервере — и правда, проблема имеет место быть.

    В статье приводится такое решение:
    $ echo "rvm_configure_env=(CFLAGS=-O3)" > ~/.rvmrc
    

    Альтернативный вариант из этой статьи:
    $ echo 'rvm_configure_env=(CFLAGS="-march=native -O2")' > ~/.rvmrc
    

    И затем:
    $ rvm reinstall your.ruby.version
    

    Тем не менее, на текущий момент все еще проще:
    $ rvm get head && rvm reinstall your.ruby.version
    

    А кроме того в 'head'-версии RVM доступен небезывестный патч от funny-falcon для последней версии Ruby — 1.9.3-p327, который делает Ruby еще быстрее (особенно при загрузке приложения). Установка также проста:
    $ rvm install 1.9.3 -n perf --patch falcon
    $ rvm use 1.9.3-perf --default
    

    После переустановки сервер показал прирост скорости более чем в 2 раза:
    $ time ruby -e "count = 0; while(count < 100000000); count = count + 1; end; puts count"
    100000000
    
    real	0m4.117s
    user	0m4.032s
    sys	0m0.012s
    

    Так что проверяйте свои сервера, ускоряйте свои приложения.
    Ads
    AdBlock has stolen the banner, but banners are not teeth — they will be back

    More

    Comments 34

      0
      Я у себя добавил вот это в ~/.rvmrc: rvm_configure_env=(CFLAGS="-march=native -O3 -pipe -fomit-frame-pointer")
        +5
        O3 достаточно опасный флаг, ИМХО. Его использование ИМХО не стоит так рекомендовать. O2 правда тут тоже не замечено…
          +1
          Чем плох O3?
            +2
            Зачастую бинарь собранный с O3 работает медленней O2. Я много где выдел рекомендаций использовать именно O2.
              +5
              О3 применяет более агрессивный инлайнинг функций, что в при недостаточном размере кеша может замедлить программу, вместо ускорения.

              Также раньше, AFAIR в старых gcc, некоторые оптимизации О3 могли привести к некорректному коду. Но в новых версиях gcc такого уже не должно быть.
            0
            Я ставил и О3 и О2, не заметил разницы что-то…
              0
              Хах, действительно — прирост в скорости ~ в 2 раза на моем сервере!
                +1
                На Intel Atom прироста не получилось.
                  0
                  У меня VDS на XEN, проц -какой-то core i5 (модель точно не вспомню)
                0
                Intel Q6600, 8GB
                andrii@andrii-serv:~$ time ruby -e «count = 0; while(count < 100000000); count = count + 1; end; puts count»
                100000000

                До:
                real 0m5.877s
                user 0m5.640s
                sys 0m0.000s

                После:
                real 0m4.285s
                user 0m4.272s
                sys 0m0.008s

                Обновил так же на макбуке, но прирост составил 100ms
                  0
                  до

                  ⇢ time ruby -e «count = 0; while(count < 100000000); count = count + 1; end; puts count»
                  100000000

                  real 0m9.820s
                  user 0m9.672s
                  sys 0m0.020s


                  после

                  ⇢ time ruby -e «count = 0; while(count < 100000000); count = count + 1; end; puts count»
                  100000000

                  real 0m2.833s
                  user 0m2.789s
                  sys 0m0.009s


                  MacBook MB991
                  0
                  Вы попробуйте на каком-нибудь достаточно крупном проекте time rake routes или time rake spec до и после… вот где более заметен прирост.
                    0
                    От CFLAGS не заметил никакого ускорения, которое не было бы в рамках погрешности. Вот патч от funny falcon действительно даёт огромный прирост. Собственно, о флагах компиляции написано тут:
                    This generally makes my ruby ~1.5% faster.
                      +1
                      Непонятно. У меня руби 1.9.3-p194 скомпилен от 1 августа, там есть нужный флаг. Сейчас обновлю до p327, посмотрим как там.
                      $ less  ~/.rvm/log/1.9.3-p194/make.log
                      [2012-08-01 12:03:08] make  -j2
                              CC = /usr/bin/gcc-4.2
                              LD = ld
                              LDSHARED = /usr/bin/gcc-4.2 -dynamiclib
                              CFLAGS = -O3 -ggdb -Wextra -Wno-unused-parameter -Wno-parentheses -Wno-long-long -Wno-missing-field-initializers -Werror=pointer-arith -Werror=write-strings -Werror=declaration-after-statement -Werror=shorten-64-to-32 -Werror=implicit-function-declaration  -fno-common -pipe 
                      

                        0
                        аналогично, только у меня скомпилировано ещё в апреле:
                        [2012-04-27 11:55:38] make 
                            CC = gcc
                            LD = ld
                            LDSHARED = gcc -shared
                            CFLAGS = -O3 -ggdb -Wextra -Wno-unused-parameter -Wno-parentheses -Wno-long-long -Wno-missing-field-initializers -Werror=pointer-arith -Werror=write-strings -Werror=declaration-after-statement -Werror=implicit-function-declaration  -fPIC 
                            XCFLAGS = -include ruby/config.h -include ruby/missing.h -fvisibility=hidden -DRUBY_EXPORT
                            CPPFLAGS =   -I. -I.ext/include/i686-linux -I./include -I.
                            DLDFLAGS = -Wl,-soname,libruby.so.1.9  
                            SOLIBS = -lpthread -lrt -ldl -lcrypt -lm
                        

                        обновление до p327 + патч от funny falcon ускорило тест из статьи на 3.8%
                          +1
                          Ну, кстати, falcon patch дал хороший прирост. Я замерял по спекам от рабочего проекта, у нас тут 600+ спек, которые выполняются 4m 30s, стало в районе 3m20s, одобряю.

                          И, собственно, это главная фича, -O3 тут мало при чем, а в этой версии статьи патч спрятан куда-то вниз в одну строчку. Его надо было поднять на самый верх и выделить большими буквами :)
                        +1
                        Более подробная статья: alisnic.net/blog/making-your-ruby-fly/
                          –1
                          RVM вроде как для development environment, a в продакшане лучше самому из исходников собрать…
                            +2
                            в продакшне, особенно если несколько апликух на одной машине — тоже очень в тему, как минимум из-за гемсетов, ну и в целом хороший тон выкатывать ровно на ту же версию рубей, на которой девелопили
                            –17
                            Вам же дали JRuby, пользуйтесь. Нет, хотим жрать говно.
                              0
                              Ну зачем же так грубо? JRuby актуален для проектов выше среднего и для него нужно минимум 1 Gb RAM, в то время как MRI прекрасно подходит для маленьких проектов и позволяет легко обходиться начальными тарифами VDS.
                                +6
                                Нет, мы хотим огрести кучу геморняка с нативными либами. И не надо про экспериментальную поддержку в 1.7
                                +1
                                Gist для rbenv + ruby-build. Одной командой ставит ruby-1.9.3-p327 с всевозможными performance патчами.
                                  +1
                                  Реквестирую такие же тесты для php и mysql.
                                  Впрочем для mysql некие современные тесты с заточкой под Intel есть (gcc, не ICC) — vbtechsupport.com/715/, где то сильно лучше, где-то хуже. Интересные современные тесты с ICC.
                                  В 2005ом были тесты ( www.mysqlperformanceblog.com/files/presentations/LinuxWorld2005-Intel.pdf ) которые чуть ли не в 2 раза показывали преимущество mysql, скомпилированного через ICC.
                                    0
                                    А вы mysql тоже из исходников ставите? Gentoo?
                                      0
                                      Не понял сарказма.
                                      Ради производительности всегда можно скачать сырцы и сделать ./configure, или даже собрать из них rpm с нужными оптимизациями.
                                        0
                                        Как всегда, вносят поправку требования к времени на развёртывание. Если у вас есть лишние 6 часов, можно и libreoffice собрать. А если в кластере два винчестера полетели, и нужно срочно две машины новые поднять, а ваш накатывающий скрипт собирает всё из исходников, то это не дело. Конечно можно заранее поднять свой репозиторий пакетов, собирать всё необходимое с оптимизациями, класть в него и поддерживать для используемых платформ, то это хороший вариант со всех точек зрения. Кроме той, что этим нужно заниматься.
                                          0
                                          Ну скажем Apache мне и так сейчас приходится собирать из исходников, потому что в CentOS нет пакета apache2-suexec-custom, и рабочий каталог suexec /var/www/ отличается от рабочего каталога virtualmin.

                                          В целом вижу в гугле что и php, и apc, и hiphop показывают 5-20% прироста от icc.
                                    0
                                    Есть еще вот такие пакеты для убунты — Next Generation Ubuntu Ruby Packages, там свежие руби с патчами и там есть ruby-switch
                                      0
                                      О, вот это крутая штука. Теперь создание свежайшего окружения, получается, не сложнее установки LAMP стало.
                                      0
                                      Не так давно аннонсировали то, что RVM теперь не всегда будет компилировать Ruby, и что если эта версия Ruby уже есть на rvm.io для вашей платформы, то будет по умолчанию устанавливаться уже скомпилированный (пруф).
                                        0
                                        заголовок желтоват
                                          0
                                          Очень впечатлен! Пересобрал с патчем от falcon, на MacBook Air многие операции (rake routes, запуск rspec тестов) стали объективно почти в 2 раза быстрее.
                                            0
                                            Проблема уже решена ребята! Теперь нужно просто обновить RVM.

                                            Only users with full accounts can post comments. Log in, please.