imageНаверняка многих мучил вопрос — какой язык и фреймворк для него выбрать для своей работы. Я тоже задумывался этим вопросом и результаты своего тестирования приведу в статье.

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

Периодически задавая себе вопрос «так что же выбрать для постоянной работы именно для себя (какой язык, какой фреймворк)?» я начал изучать всеобъемлющий гугл на предмет сего ответа. И был, однако, удивлен, т.к. нужной мне информации не нашел. Все статьи скатываются до того, что все языки и фреймворки хороши, особенно для отдельных задач и нельзя сказать — кто победитель. Мол, хочешь знать ответ — попробуй всё и реши для себя сам.

С последним утверждением я полностью согласен, но мне не хватило бы простого субъективного ответа, я захотел цифр. Тогда придумал взять набор задач, чтобы сравнить языки программирования, а также фреймворки и их привычный функционал. Т.к. я работаю на PHP, первым делом начал с выбора фреймворков именно для этого языка. Сейчас протестированы: Yii2, Laravel5. Взяты именно они, т.к. являются самыми популярными фреймворками на PHP (да, Symfony, про тебя тоже помню).

Из других языков (и фреймворков) были взяты JS (NodeJS + SailsJS) и Ruby (Rails), т.к. с ними тоже был определенный уровень знакомства.

Сразу разъясню, почему были взяты именно эти языки/фреймворки.

Главная цель для меня — выбор технологий для разработки будущих проектов, как моих, так и компании, где я работаю. Конечно, субъективную оценку цифрами не обозначишь, поэтому в результирующих таблицах будут только количественные показатели. В целом, я пришел к выводу, что мне удобны php и ruby + обозначенные выше фреймворки примерно в одинаковой мере. А вот разработка на nodejs мне не показалась такой удобной, быстрой и клёвой.

Итак, тесты производительности определенных задач для языков:



Первый тест — генерация числа Пи с количеством итераций = 100000000.
Далее идет тест по генерации Множество Мандельброта.
После — генерация экспоненты с помощью самого языка, а также с помощью имеющихся у языка дополнительных библиотек.

Результаты, на самом деле, были не очень удивительны — nodeJS уверенно идёт впереди планеты всей.

Очень порадовал PHP7 — очень хорошо чувствуется поднятие производительности в 7 версии по сравнению с 5.6. А вот почему результаты тестов генерации экспоненты с либами дали такой результат — пока не совсем понял.

Далее были протестированы фреймворки:



Тест очень просто и типичный для простых сайтов — достать информацию из базы, отправить на рендер в представление и вывести в буфер.

В данном случае берутся 3000 строк из Mysql из 10000 строк в базе и строится пагинация.

Вот тут SailsJS, если честно, удивил. Я ожидал, что всех своих конкурентов он резво уделает. А он ни то, что не уделал, но еще и проиграл Laravel'у.

Всё тестировалось без кэширования. При включенном кэшировании данные, конечно же, несколько другие, но картины не меняют.

Вывод


Буду продолжать тестировать языки и фреймворки на предмет скорости и удобства. На данном этапе ближе всего по удобству/скорости разработки и скорости работы приложения, организации кода для меня — Laravel.

Приветствуются замечания, комментарии и pull-реквесты в мой репозиторий.

Комментарии (36)


  1. DexterHD
    18.01.2016 21:04

    Вывод в node.js вы конечно же в sync режиме использовали???


    1. AxelPAL
      18.01.2016 21:29

      Использовал конфиг SailsJs, шедший из коробки.


  1. dim_s
    18.01.2016 21:41
    +1

    Node.JS это не язык, а платформа с использованием движка V8 для js.


    1. AxelPAL
      18.01.2016 21:48
      -3

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


  1. Leopotam
    18.01.2016 21:44
    -3

    А так же поправить табличку потребления памяти у Laravel с учетом вебсервера (потому что nodejs — это полноценный сервер приложений, включая http-сервер).


    1. AxelPAL
      18.01.2016 21:54
      -2

      Ну собственно, как и у руби — WEBRick — полноценный веб-сервер. Хоть и используемый обычно в dev-окружении.


      1. fuCtor
        19.01.2016 12:48

        Хоть и используемый обычно в dev-окружении.

        Кем используемый о_О давно уже первым делом в dev прописывается как минимум thin.


    1. DexterHD
      18.01.2016 21:56

      php -S localhost:8000 (Хотя некорректно сравнивать потому что оно тока для разработки и работает медленно. Ни кто там за скоростью не гнался).


  1. ckr
    18.01.2016 21:59
    +2

    Всё тестировалось без кэширования. При включенном кэшировании данные, конечно же, несколько другие, но картины не меняют.

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

    Столбик Memory consumption во второй таблице немного непонятен.
    В случае с Laravel и Yii, как я понимаю, показывает heap процесса после отработанной генерации одной странички.
    А в случае с Rails и SailsJS Вы показываете heap всего сервера.
    Что из этого следует? Если, например, запустить одновременно 10 потоков генерации странички Laravel, то объем общей занятой памяти на тестируемый момент будет 19.32 ? 10 = 193.2Mb. В этих же условиях, не факт что Rails и SailsJS принципиально увеличат объем занятой памяти.


    1. AxelPAL
      18.01.2016 22:46
      -6

      Кэширование тоже бывает разным. Но интереса ради включу везде кэширование и проведу отдельный тест.
      По поводу замера размера памяти — я, конечно же, понимаю, что так сравнивать не совсем корректно, но руби и нода стартуют сервером, в то время как встроенный сервер php — совсем не производительное решение.
      Как вариант, конечно, перевести всё на один веб-сервер + подключить обработчики для языков. Хотя нода в любом случае будет запускать свой сервер, к которому нужно будет делать upstream.


      1. ckr
        18.01.2016 23:07
        +1

        Кэширование тоже бывает разным.

        Платформы тоже могут быть по-разному настроены. В NodeJS есть возможность загрузить какие-то данные в память один раз и пользоваться этими данными при выдаче каждой страницы. В php такое возможно лишь с использованием memcached и их аналогов. Существует также LRU-cache — это как кэш кэша. Значения наиболее популярных блоков памяти хранятся в одном массиве для наиболее быстрого доступа к ним.
        Также, результаты могут отличаться как в лучшую, так и в худшую стороны, если php будет запускаться с какими-нибудь ioncube, zend optimizer, eAccelerator.
        Для сравнительных тестов NodeJS, Ruby и PHP было бы справедливо суммировать затраченную память и CPU-time всех PHP-процессов и всех процессов вебсервера — Apache или Nginx или что-то еще (вы не указали).
        Советую проводить нагрузочные тесты вот этой утилитой:
        httpd.apache.org/docs/2.0/programs/ab.html


      1. Source
        19.01.2016 10:42
        +1

        в то время как встроенный сервер php — совсем не производительное решение
        Вы так пишете как-будто Webrick (встроенный сервер для Ruby) — производительное решение. Добавьте в Gemfile строку
        gem 'thin'
        

        и посмотрите ещё раз (после bundle install).

        А по теме статьи, Вы по сути выбираете из медленных технологий. Рассмотрите Elixir+Phoenix и Golang+Gin, если производительность без кеша имеет значение для вас :-)


  1. DexterHD
    18.01.2016 22:05

    Идиотский вопрос, но вас не смутило, что в PHP константа M_PI, это аналог функции pi() — и она вычисляет PI с заданой в php.ini точностью, ВЫЧИСЛЯЕТ. А в JS Math.PI — как я понял тупо предопределенная константа, те число зашитое в исходник? Если я не прав, расскажите, как изменить точность Math.PI или ткните меня в исходники бибилотеки Math для JS.


    1. ckr
      18.01.2016 22:11
      +5

      Загляните в исходники тестов, там имелся в виду тест простого алгоритма вычисления pi.
      Конечно, M_PI и Math.PI это константы, и никто не собирался их рассчитывать в продакшене.
      Суть в том, чтобы запустить один и тот же алгоритм на разных языках/платформах.


      1. DexterHD
        18.01.2016 22:14

        Да я идиот, извиняйте, я че то на ссылку внимания не обратил…


  1. farcaller
    18.01.2016 22:19
    +1

    В третьем тесте у питона 0.44s, а у ноды 0.68s. Я что-то не понимаю в выделении жирным?


    1. AxelPAL
      18.01.2016 22:40
      -3

      Да, немного ошибся. После обновления до 5 версии ноды стали такие результаты. Жирность не поменял. Спасибо за замечание.
      Можете в коммитах посмотреть, какие показатели были на 0.12.7 версии ноды.


  1. DexterHD
    18.01.2016 22:53

    Забавно, но если просто обернуть PHP код из репозитория, для генерации Pi в класс и метод, то даже PHP 5.6 справляется за 4.8 секунд, смею предположить, что результат PHP 7 будет быстрее. Не знаю с чем это связано, но есть какой то подвох. Может связанный с объявлением глобальных переменных.

    В то же время если обернуть JS, ни чего по таймингу не изменится.


  1. ckr
    18.01.2016 23:52
    +3

    Да, еще одно замечание автору. Не совсем по теме статьи, но я посчитал полезным и оставлю здесь.

    В исполняемом скрипте SailsJS app.js Вы обернули код в конструкцию:

    (function(){
    })()
    

    Данность явно указывает на то, что javascript вы знаете по front-end-у.

    Такая конструкция уместна для изоляции переменных и прочего кода в браузерах, так как все скрипты работают с одной областью видимости window.
    В Node.JS каждый модуль запускается в собственной области видимости module. Такая обертка у чисто серверного скрипта выглядит весьма странно.

    Гораздо большего эффекта можно добиться, например, от strict-режима, чего в ваших скриптах не наблюдается:
    'use strict';
    


    1. AxelPAL
      19.01.2016 07:34
      +1

      В случае с SailsJS использовал генератор проекта от самого Sails. Он и создал такой файл, его я не менял.
      И вообще, если в фреймворке есть средства генерации кода — я его использовал. Это касается всех приведенных в статье фреймворков.


      1. ghaiklor
        19.01.2016 11:36

        А лучше вы бы этот использовали — github.com/ghaiklor/generator-sails-rest-api
        Тот генератор, который идет в поставке с Sails, убогий и ничего толкового не умеет.


  1. asavin
    19.01.2016 00:37

    комментарий удалён


  1. hell0w0rd
    19.01.2016 01:20
    +1

    Инструменты надо выбирать по задачам. Если у вас админка — в принципе наплевать, сколько будет генерироваться ответ с сервера, зато важна скорость разработки.
    Если у вас реалтайм и вебсокеты, php в принципе рассматривать не стоит, не для этого он сделан.
    А если уж тестируйте — делайте это правильно. У вас, судя по коду, куча копипасты с SO, или аналогов. Напишите везде один и тот же алгоритм.
    Как вы тестировали затрачиваемую память — вообще не ясно.


  1. SirEdvin
    19.01.2016 02:32
    +1

    Очевидно, есть какая-то странность, что NodeJS так всех обогнал.
    Не могу только понять какая…


    1. VolCh
      19.01.2016 09:23
      -2

      Компиляция в нативный код?


  1. Regis
    19.01.2016 02:45
    +3

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


  1. Bringoff
    19.01.2016 08:57
    +2

    Интересно, и часто в проектах на PHP и RoR приходится экспоненту вычислять?


    1. AxelPAL
      19.01.2016 10:13
      -2

      Первый тест — вычислительная задача, чтобы количественно сравнить php/ruby/js+node.
      Практического смысла, понятное дело, не имеет. Это показатель того, как языки (и нода) справляются с вычислениями.
      Второй тест — более приближенный к жизни, хоть и показывающий простой и банальный use-case приложения.


    1. poxu
      19.01.2016 11:23
      -1

      Да в общем никогда. Как и использовать PHP и RoR, если нужна производительность.


      1. VolCh
        19.01.2016 11:35
        +3

        Фэйсбуку и Гитхабу производительность не нужна? :)


        1. poxu
          19.01.2016 14:36
          +4

          У Фейсбука столько легаси кода, что переписать его не получилось. Оказалось проще написать сначала транслятор в си, а потом свою виртуальную машину для php. Которая по производительности всё равно проиграет банальной джаве, не говоря уже о каком-нибудь Go. Если бы отыграть время назад, никто бы и не подумал делать Фейсбук на php. На одном только электричестве сэкономить миллионы можно.

          У гитхаба запросы по производительности в сотни раз меньше, ему хватает того, что есть


          1. VolCh
            19.01.2016 18:34

            Если бы отыграть время назад, никто бы и не подумал делать Фейсбук на php.


            С одной стороны, история не знает сослагательного наклонения, а, с другой, не думаю, что Цукерберг бросился бы изучать Java, обладая сегодняшними знаниями о том как взлетела поделка на PHP. Там может задержка релизов на день была критична.


            1. poxu
              19.01.2016 21:16

              Собственно так и есть. Делать не на том, чем владеешь, а на чём то другом обычно крайне неудобно.


  1. komandakycto
    19.01.2016 12:44

    Мне показалось, что поставленная задача (цель) не коррелирует с проведенными исследованиями


  1. bromzh
    19.01.2016 13:09
    +1

    Зачем, если уже есть www.techempower.com/benchmarks
    Там хоть данные, близкие к практическим, т.е. работа с сетью, а не числодробилки и рекурсии, которые на практике оптимизируют по-всякому.


  1. maxru
    19.01.2016 16:44

    Хотелось бы хотя бы в общих чертах понять, какие насущные проблемы в web-программировании решает скорость вычисления числа PI.