Comments 61
После прочтения статьи остались вопросы. Скорость на синтетических тестах — это, конечно, хорошо, но как обстоят дела с памятью и отказоустойчивостью? Вот, например, разработчики Phoenix говорят, что не имеют проблем при работе с огромными (порядка миллиона, если мне не изменяет память) количествами коннектов по вебсокету к одной ноде. С другой стороны у go могут начаться проблемы из-за сборки мусора.
Я так и не понял, в чём преимущество вашего фреймворка перед Symfony, Laravel или Phalcon? Symfony мне нравилась тем, что в ней всё работает, как в доках, пусть даже они и не всегда хорошие, а код на ней получается очень чистым, без лишнего хлама. Laravel простая, как пять копеек, даже не смотря на отвратительную производительность, полный треш в пакетах и чудачества eloquent, у неё всё равно есть своя область применения. У вас я открыл быстрый старт в документации, а там мне предлагают писать обработку аннотаций роутера или пользоваться каким-то странным классом с шаблонным кодом. Я что-то не так понял или и правда нужно нажимать так много лишних кнопок? Ну, да, пёс с ним, пользователи Лары как-то живут с её роутингом и ничего. Вы пишете, что в основном в фреймворк используется в b2b, но я так и не смог придумать ни одной причины, почему там нужно использовать интеграцию с го и не хватит просто php или питона, например. На каких задачах он сможет полноценно раскрыть свой потенциал?
почему там нужно использовать интеграцию с го и не хватит просто php или питона, например.
Если вопрос в принципе про использование сервера приложений roadrunner, он убирает оверхед на создание инстанса приложения на каждый запрос, что даёт хороший буст производительности, и легко добавляется даже в уже существующие приложения, в т.ч. на Symfony/Laravel.
Не понятно, за счет чего возникает «хороший» прирост производительности. Особенно если добавить это в существующее приложение на, допустим, laravel.
За счёт того что не нужно инициализировать всё приложение, зависимости, сервисы и т.п. на каждый запрос, работа идёт в скрипте-демоне.
Конечно, неэффективный код приложения, если таковой есть, не особо ускорится, ну и нужно будет учитывать при разработке, что процесс после запроса не завершится и не почистит всё за собой.
что процесс после запроса не завершится и не почистит всё за собой
Т.е. придется доработать приложение что бы оно за собой еще и подчищало данные? А потом всегда в голове это держать и не забыть зачищаться? Если да, то вижу я в этом усложнение процесса разработки и море багов связанных с этим.
Именно так, придётся писать приложения как это принято в любом другом языке программирования.
Задача фреймворка как раз упростить разработку таких приложений и избавить вас от большинства багов.
Т.е. придется доработать приложение что бы оно за собой еще и подчищало данные? А потом всегда в голове это держать и не забыть зачищаться? Если да, то вижу я в этом усложнение процесса разработки и море багов связанных с этим.
C#, Java, Scala, NodeJS, да практически всё что угодно ― на них сервера пишут именно так.
Symfony на Swoole веб-сервере быстрее работает - https://www.techempower.com/benchmarks/
Спасибо за большой комментарий.
Скорость на синтетических тестах — это, конечно, хорошо, но как обстоят дела с памятью и отказоустойчивостью?
Все хорошо, мы написали rr как раз для того чтобы приложения выдерживали резкие нагрузки. Память зависит от количества воркеров и объема вашего приложения. Про поведение сервера под нагрузками можно почитать тут — https://habr.com/ru/post/431818/ (на ядре Symfony).
Я так и не понял, в чём преимущество вашего фреймворка перед Symfony, Laravel или Phalcon? Symfony мне нравилась тем, что в ней всё работает, как в доках, пусть даже они и не всегда хорошие, а код на ней получается очень чистым, без лишнего хлама. Laravel простая, как пять копеек, даже не смотря на отвратительную производительность, полный треш в пакетах и чудачества eloquent, у неё всё равно есть своя область применения.
Мы больше склоняемся к модели Symfony, но используем работу как со стеком (middleware) Laravel. Код не сильно отличается от этих фреймворков, и, пожалуй, не должен отличаться. Плюсом можно назвать то что для запуска даже сложного приложения вам не потребуется ставить зоопарк инструментов.
У вас я открыл быстрый старт в документации, а там мне предлагают писать обработку аннотаций роутера или пользоваться каким-то странным классом с шаблонным кодом. Я что-то не так понял или и правда нужно нажимать так много лишних кнопок?
Нет не нужно, просто аннотированный роутинг самый частый вопрос на который пока нет расширения из коробки, вот его и включили в обзорную статью. В самом начале упоминается что роутинг можно определять руками. Постараемся отполировать данную часть.
Вы пишете, что в основном в фреймворк используется в b2b, но я так и не смог придумать ни одной причины, почему там нужно использовать интеграцию с го и не хватит просто php или питона, например. На каких задачах он сможет полноценно раскрыть свой потенциал?
Сейчас мы пишем в основном распределенные проекты, в таких приложениях вы можете получить максимальную пользу от фреймворка за счет встроенных инструмент.
Мне непонятно, почему нет тестов чистых golang фреймворков? Я просто сильно сомневаюсь, что скрестив гепарда с улиткой вы выиграете в производительности у гепарда.
Мне непонятно, почему нет тестов чистых golang фреймворков? Я просто сильно сомневаюсь, что скрестив гепарда с улиткой вы выиграете в производительности у гепарда.
Вряд ли у ребят есть цель обогнать golang по производительности
Привет, это именно PHP фреймфорк, так что с точки зрения PHP разработчика ничего не меняется. Golang компилируется в бинарный файл и не беспокоит вас своим присутствием.
так что с точки зрения PHP разработчика ничего не меняется
Как не меняется, если «после каждого запроса приложение должно зачищать за собой»?
Это делает сам фреймворк за ваc.
В приложении на spiral — нет, мы изначально разработали архитектуру для работы в режиме демона. Насчет существующего приложения не скажу, зависит от фреймфорка и вашего кода.
В приложении на spiral — нет, мы изначально разработали архитектуру для работы в режиме демона. Насчет существующего приложения не скажу, зависит от фреймфорка и вашего кода.
Ну, при желании, полагаю, можно наделать всякого нехорошего.
Но я бы сказал что писать приложения которые не готовы жить в формате демона и полагаются на перезапуск на каждый запрос — не очень хороший тон в принципе.
Подскажите, пожалуйста, что значит "архитектура для работы в режиме демона"? Может быть пример на словах, как вы архитектурно что то разрулили. Просто мне кажется дело в коде больше, чем в архитектуре. Либо я что то не понял..
Ps.Пробовали road runner, получили неплохой буст! Проект на симфони, код был готов к долгоживущим работам
Подскажите, пожалуйста, что значит «архитектура для работы в режиме демона»? Может быть пример на словах, как вы архитектурно что то разрулили. Просто мне кажется дело в коде больше, чем в архитектуре. Либо я что то не понял..
Типично:
Традиционно PHP на каждый запрос стартует, инициализируется, выполняет. Умирает целиком, нет необходимости очищать ресурсы по окончании запроса.
В режиме демона — нет старта частого. Нужно аккуратнее относится к ресурсам занимаемым.
Работа с переключением контекста запроса сделана на уровне ядра контейнера, большинство критичных сервисов иммутабельны, работа со стеком вместо работы с событиями. Все познавалось на горьком опыте и верифицировалось на живых проектах.
Про это мы расскажем на конференции. :)
Если кратко: стек может гарантированно заменять события, но не наоборот. При событиях обработка данных происходит вне контекста запроса, и требует множество костылей (before, after, stop propagation, priorities). Отдельно стоит отметить обработку ошибок, какая именно цепочка событий отработает предугадать сложно.
Если в приложении такое дебажить еще как-то можно, то в долгоживущем 60% проблем на ранних стадиях находилось в событиях и хуках.
Стеки же гарантированно ограничивают контекст приложения в момент запроса, если запрос заканчивается (ошибкой или нет) то вы гарантированно выйдете из стека и востановите состояние.
А еще стеки можно вкладывать друг в друга, добиться такого с ивентами в глобальном инстансе приложения без проблем практически невозможно.
Мне непонятно, почему нет тестов чистых golang фреймворков? Я просто сильно сомневаюсь, что скрестив гепарда с улиткой вы выиграете в производительности у гепарда.
Дело не в этом.
А то давно бы весь мир писал только на Java или Go, а PHP и Python умерли бы.
Есть другие соображения, кроме производительности исполнения кода.
Скажем, как легко найти исполнителей на PHP и сколько они стоят.
И как легко и сколько — если Go.
Недостаток производительности сервера легко компенсируется небольшими деньгами.
А вот недостаток программистов — компенсируется только огромными деньгами.
Или большая скорость прототипирования на динамических языках против большей надежности на статических. А скорость для современного бизнеса — это крайне важно.
Скажем, как легко найти исполнителей на PHP и сколько они стоят.
И как легко и сколько — если Go.
Дык апологеты Go пишут что почти любого программиста можно за пару дней превратить в Go-программиста, в виду того, что язык спроектирован так, что его легко учить и можно чуть-ли ни с места в бой. Врут?
В моей предыдущей конторе несколько человек быстро перешло на Go и остались довольны. Как раз PHP разработчики.
Скажем, как легко найти исполнителей на PHP и сколько они стоят.
И как легко и сколько — если Go.
Дык апологеты Go пишут что почти любого программиста можно за пару дней превратить в Go-программиста, в виду того, что язык спроектирован так, что его легко учить и можно чуть-ли ни с места в бой. Врут?
В моей предыдущей конторе несколько человек быстро перешло на Go и остались довольны. Как раз PHP разработчики.
Изучить язык легко.
Практически любой.
Но вот изучение библиотек, инструментов, хотя бы просто узнать о существовании GoDoc, изучение специфических паттернов написания алгоритмов для именно этого языка. и т.п. «мелочи», а также когда вы на каждый чих лазаете по интернету в поиске «а как эту вещь сделать на этом языке» — это очень много времени, когда ваша производительность серьезно снижена. Нормальный миддл при переключении стека на время превращается в джуна — только и делает, что гуглит целыми днями.
Но обстоятельства любого бизнеса таковы — что результат нужен еще вчера, а после переключения на новый языковый стек производительность труда серьезно снижается. Поэтому должна быть серьезная причина переключения стека.
Я «переключал стек» у новичков, что приходили к нам, занимало это 2 недели моего личного времени. Это было выгодно и перспективно и окупилось в течении 2-х лет, так как предполагалось (и предположения оправдались), что новички будут работать у нас минимум 2 года.
Но вот например сейчас мне уже через 1,5 месяца нужно выдать готовый продукт. Который сам по себе имеет хитрые ньюансики внутри, которые я еще не знаю как мы реализуем. А тут еще и новый стек? И в этих услових обучать новичков, а потом наблюдать за рушащимся сроками deadline — совсем не хочется. В этих условиях я возьму уже того, кто умеет.
github.com/rryqszq4/ngx_php7
По бенчмаркам TechEmpower легко обходит Swoole, Workerman, Load Runner и даже (неожиданно) LuaJit и фреймворки на Go.
Привет, трудно судить по бенчмарку учитывая что там чистый PHP — https://github.com/TechEmpower/FrameworkBenchmarks/blob/master/frameworks/PHP/php-ngx/app.php
Достаточно большой оверхед создают ORM и другие части фреймворков, так что такое сравнение не совсем честное.
рукалицо, да в каких розовых снах вы такое увидели?)
Ссылки на бенчмарки доступны в статье, самим удивительно. Вот последние результаты: https://www.techempower.com/benchmarks/#section=test&runid=c7013ea3-22c9-44c1-864f-949509d78e0c&hw=ph&test=fortune&l=zik073-1r&c=6
Само собой синтетика не показатель, но результаты не в пользу Phalcon.
yii2 | laravel | symfony | phalcon | spiral
14,984 | 5,654 | 7,056 | 12,430 | 34,644
а в оригинальном:
13,530 | 5,484 | 1,213 | 23,318 | 0
Если небольшое отличие для yii2 и laravel можно назвать погрешностью, улучшенные результаты symfony оптимизацией за последние полгода (с момента последнего официального пересчёта рейтинга), то просадку phalcon почти в 2 раза никак не объяснить. Что собственно и вызвало удивление у stanlee и у меня.
Я правильно понимаю, что ваши тесты были добавлены в код оригинального бенчмарка только относительно недавно (пару месяцев назад) и вы займёте какое-то место в общем рейтинге только где-то через полгода?
Тогда если ваши текущие результаты нанести на текущий общий рейтинг, то выглядеть он будет приблизительно так:
![](https://habrastorage.org/webt/pf/ix/oa/pfixoaftreoexrapwelbnqefn8a.png)
т.е. в среднем в два раза быстрее yii2, laravel, symfony и phalcon, и в 10 раз медленнее чем workerman и swoole.
Что ж, вам есть куда расти. Не останавливайтесь на достигнутом. Если до swoole, который на C++/C, будет сложно угнаться, то достигнуть результатов workerman, который написан на чистом PHP, это уже вполне реально.
У вас есть ещё полгода до общего пересчёта рейтинга, чтобы успеть показать ещё лучшие результаты.
Я правильно понимаю, что ваши тесты были добавлены в код оригинального бенчмарка только относительно недавно (пару месяцев назад) и вы займёте какое-то место в общем рейтинге только где-то через полгода?
Все верно, ждем следующий раунд.
Если до swoole, который на C++/C, будет сложно угнаться, то достигнуть результатов workerman, который написан на чистом PHP, это уже вполне реально.
Я не уверен что в принципе возможно обогнать чистый Swoole на полноценном фреймворке с ORM и шаблонами. Если смотреть на пример Symfony+Swoole то отставание на 29%, а не в 10 раз. До самого дальнего фреймворка на Swoole/Workerman отставание в 4-5 раз, чего трудно добиться без жертв со стороны архитектуры.
Я не уверен что в принципе возможно обогнать чистый Swoole на полноценном фреймворке с ORM и шаблонами.Судя по всему в следующем раунде мы так же увидим swoft (фреймворк на основе swoole). Его код уже присутствует в бенчмарке. Будем ждать пересчёта. Будет на кого ориентироваться.
Swoft уже есть, ориентировочно в два раза быстрее спирали.
Судя по всему в следующем раунде мы так же увидим swoft (фреймворк на основе swoole). Его код уже присутствует в бенчмарке. Будем ждать пересчёта. Будет на кого ориентироваться.
Стоит упомянуть, что Swoft/Swoole асинхронные, в отличие от, так что в реальных приложениях при должном использовании они всегда будут быстрее.
Вопрос «насколько сильно».
Например, workerman на тестах медленнее swoole в два раза, а на моих задачах «всего» на 10-20%, но мне гораздо приятнее работать с workerman, чем со swoole, поэтому я готов на такие «жертвы», лишь бы не читать документацию на китайском, спрашивать у разрабов, за что отвечает тот или иной магический параметр, у которого нет описания даже на китайском и т.д. С workerman я могу в любой момент залезть в код и разобраться что там, и как и даже что-то поправить и отправить пуллреквест.
Только оригинальный репозиторий вот этот — https://github.com/TechEmpower/FrameworkBenchmarks
Спасибо большое за вашу работу. Реквестирую расширить документацию к RoadRunner — реально по крохам между страницами приходится понимать базовые вещи (те же golang middlewares). Такое ощущение, что писатель документации взял за цель минимизировать количество текста, оставив только чистую эссенцию новой информации.
Ещё бы реквестировал доку или пример работы не через php-cli, а через php-cgi в командной строке. В теории оно должно работать, на практике пока сложновато продраться через дебри.
Ещё вопрос, почему внутри используется zend diactaros, а не laminas diactaros? То есть ругающийся composer update иногда настораживает.
Ещё вопрос, а возможно ли заменить тот же diactaros на другой? например, более быстрый Nyholm\Psr7?
Ещё вопрос, а не рассматривали подход с fasthhttp? В теории, так как воркеров ограниченное количество, можно сделать ± zero memory allocation работу, или хотя бы минимизировать это дело.
В теории go-часть может ждать в Stdout первый бит или байт, если он допустим, «1» — это означает, что сейчас придёт response, если он «2» — сейчас придёт вызов RPC от PHP части, надо будет обработать и передать ответ назад, а PHP часть в свою очередь будет считывать свой STDIN.
Можно, но для этого придется модифицировать протокол. Поддержка асинхронных клиентов задумана в 3й версии.
Ну и ещё вопрос: а можно ли STDIN и STDOUT пайпы (через которые гоняют данные PHP и golang) приспособить для вызова RPC методов? Я так понимаю, эти пайпы самый быстрый способ обмена между ними, быстрее чем линукс-сокеты или обычные локальные сетевые соединения?..
Unix-сокеты довольно шустрые.
Если для вашей задачи настолько важна производительность этой части — то есть смысл задуматься о смене языка PHP на что-то шустрое (тот же Go).
Но, практически, здесь socket/local net/etc не является узким местом. СУБД куда как более значительный тормоз вашей системы.
В теории go-часть может ждать в Stdout первый бит или байт, если он допустим, «1» — это означает, что сейчас придёт response, если он «2» — сейчас придёт вызов RPC от PHP части, надо будет обработать и передать ответ назад, а PHP часть в свою очередь будет считывать свой STDIN.
STDIN/STDOUT — это неудобно для мультиплексирования, но, да — возможно.
Посмотрите, к примеру, как реализован протокол WebSocket. Если отвлечься от того, что это сетевой протокол, то внутри он реализует обмен по одному потоку.
(Отвечая на вопрос «зачем» — экспериментирую, можно ли сделать общий кеш запросов между всеми воркерами).
Привет,
Такое ощущение, что писатель документации взял за цель минимизировать количество текста, оставив только чистую эссенцию новой информации.
Так и есть, покрыть такое количество материала достаточно сложно с первого раза.
Ещё бы реквестировал доку или пример работы не через php-cli, а через php-cgi в командной строке. В теории оно должно работать, на практике пока сложновато продраться через дебри.
CGI интеграцию еще не делали.
Ещё вопрос, почему внутри используется zend diactaros, а не laminas diactaros? То есть ругающийся composer update иногда настораживает.
В процессе переключения, ничего не хотим сломать.
Ещё вопрос, а возможно ли заменить тот же diactaros на другой? например, более быстрый Nyholm\Psr7?
Без проблем, фреймворк как раз и использует Nyholm по умолчанию.
Ещё вопрос, а не рассматривали подход с fasthhttp? В теории, так как воркеров ограниченное количество, можно сделать ± zero memory allocation работу, или хотя бы минимизировать это дело.
Есть в пайплайне, но большого прироста не ожидаем так как боттлнек на стороне PHP.
Ещё вопрос, почему внутри используется zend diactaros, а не laminas diactaros? То есть ругающийся composer update иногда настораживает.
Войдет в 1.7.1 релиз. :)
Не нашел в обсуждениии, но очень интересно — в 20 году планируется выход PHP8, RoadRunner и Spiral будут с ним работать? Наверное больше интересует будет ли корректно взаимодействовать RoadRunner с кодом на PHP8?
Добрый день. Не вижу ни одной причины почему код может не работать, с 7.4 у нас проблем нет, старую магию давно выпилили.
В общем, мне со своей колокольни видеться, что: а) spiral фреймворк — детище принципально новое, где в придачу go-lang реально в пользу. б) Если при этом бенчмарки не врут и на деле значительный выигрыш в производительности + сделан акцент на упрощение разработки (сравнивая с тем же symfony, сам больше приверженец модульности). в) В окружении семейный ряд инструментов (RR!!, ORM, Toolkit etc.) для покрытия основной части нужд для полноценной фулстэк работы,
то определенно фреймворк достоен внимания, хотя и пока — понятно — без популярности дедов, но, хочу отметить, тут номером 1 стоит вопрос о полноте документации, и чтобы даже зеленый php ламер мумел по ней найти путь…
Честно, пока толком руки не доходят до практико-изучения сего инструмента, но, есть планы в скором засучить рукава, будем видеть :))
Spiral: высокопроизводительный PHP/Go фреймворк