Pull to refresh

Comments 104

А вечный цикл не будет грузить процессор на 100%?

Это не вечный цикл, управление отдается ядру, которое оповещает приложение о событиях. В случае с Linux это epoll API, в случае с BSD/OSX это kqueue/kevent API.


А в ядре вечный цикл и так есть ;)

stream_select — это очень, очень плохой вариант, он каждый раз будет итерировать все неактивные соединения. Так, поиграться в песочнице, в которой родители запрещают делать pecl install.


Но там есть и полноценные драйвера, годные для продакшена: Uv, Ev, Event.

Проблема с асинхронщиной не столько даже в том, что не получится использовать стандартные расширения типа PDO (в конце концов, их можно один раз переписать), сколько в том, что появляется явное разделение на синхронные и асинхронные операции. Скажем, тот же lazy load прозрачно реализовать невозможно — сразу же меняется API (функции вместо value уже возвращают Promise<typeof value>). Если на nodejs к этому все привыкли, и Promise и так уже возвращается везде, где можно и нельзя, то на PHP это приведет к необходимости переписать не только инфраструктурные библиотеки и расширения, а вообще все, ведь меняется не только реализация, но и контракты.


Интересным вариантом на уровне языка мог бы быть неявный await по умолчанию, с неявным "анбоксингом Promise", а для отсутствия ожидания — явное ключевое слово, "обратное" await. Скажем, go :-) Тогда можно было бы заменить расширения типа PDO на асинхронные варианты, возвращающие Promise, и получить прирост производительности вообще без изменения существующего PHP-кода.

Вряд ли так будет.
Возможно, к 8 добавят event loop в ядро, возможно, еще некоторые примитивы.
Из остального скорей всего всего что-то будет понемногу перетаскиваться, что-то перейдет в какие-то ffi-подключаемые расширения как nghttp2 в amphp/http-client, а какая-то часть так и останется. Скорость PHP растет и большинство из решаемых тут задач переписывать на что-то другое смысла нет или не будет уже в ближайшем времени.

Я понимаю, что так не будет :-)
Но евент-лупах тоже особого смысла не вижу — это просто повторение модели node.js с опозданием в 10 лет.

UFO just landed and posted this here

С асинхронным API можно перейти от модели "один процесс одновременно обрабатывает один запрос" к модели "один процесс обрабатывает в event loop множество запросов".
Поскольку на PHP обычно пишут I/O-bound, а не CPU-bound приложения, этот подход отлично работает. ReactPHP и прочие AMPHP именно это и делают, но ценой несовместимости с существующей кодобазой.


Конечно, совсем автоматически переход на подобное SAPI не получится, надо будет еще избавиться от глобальных состояний типа суперглобальных переменных — но для вменяемо написанных фреймворков, избегающих глобальных состояний (Symfony, например), это не проблема, изменений минимум.

1) из коробки отсутствие задержек на переключение контекста дважды на каждый ввод/вывод
2) опционально возможность инициализироаать приложение только один раз, банально конфиги прочитать только один раз, инициализироаать всю инфраструктуру, создать пул соединений к базе, другим сервиса, инстансы классов типа ядра и на каждый запрос создавать только request, response и то, что нужно для превращения первого во второй. Вообще количество new может сократиться на порядки на один запрос. Плюс дешёвое кэширование, хотя отладка может в ад превратиться.

Вообще хотелось бы верить, так как я очень люблю использовать что Amp, что какие-то компоненты от ReactPHP, в домашних поделках и мне зашло гораздо лучше, чем node.js, но пока о востребованности всего этого счастья только мечтать. Несколько раз попадались высказывания, что у кого-то даже в production вертится, однако упоминаний в вакансиях нет вообще, да и каких-то «историй успеха» на этом же хабре тоже не видать.
У меня оно вертелось в продакшн и довольно долго, но, увы, оно того не стоит. Работает в принципе стабильно, но поддерживать сложно. Искать ошибки сложно, а работа с тем же RabbitMQ превращается в ад.

Node в этом плане гораздо удобнее.
Вообще никаких проблем не было с RabbitMQ. Использую библиотеку bunny. О каком аде речь?
О визуальном аде. Ее и использовал. Промисы на промисах с промисами. В PHP это выглядит ужасно, увы.
В amphp можно же эвейтить через yield, да и для реакта прикручивается recoil.
Я не сразу разобрался как правильно писать код, но при определённом подходе это не очень ужасно выглядит. Да и суть в том, что действительно можно завернуть всё в yield.
А насколько это было «продакшн»? В своих каких-то проектах, иногда даже публично торчащих в окружающий мир, используется и у меня, но вот в серьезном проекте, за который чужой дядя платит деньги или будет платить, я еще не встречал.

Можно группировать какую-то работу с io, запихивать в Amp\Promise\wait() между синхронного кода и это более-менее решает проблему поддержки и ошибок, позволяя попользоваться асинхронностью. Но у меня это единичный случай и что будет если штук 50-100 php-fpm воркеров будут одновременно вращать свой event loop я не знаю, поэтому это под определенную специфику вариант.

Нода очень не нравится, поэтому и надеюсь что это будет развиваться в PHP.
Или если не пойдет, то уже буду ориентироваться на .net core.
Ну, ссылка в профиле. Можете оценить серьезность проекта.
«Дядя», который платит за проект — это я в данном случае. Но конечно не хайлоад с миллионами пользователей, чего нет того нет.

На данный момент ReactPHP используется в паре сервисов из-за удобных таймеров для мелких периодических задач. А раньше на нем работали сервисы по парсингу/формированию файлов которые создавали кучу форков, следили за всем этим и пр. Это давно было, так что какие-то детали и не помню честно говоря.

Еще пробовал делать чат на reactPHP, там есть реализация вебсокетов. Ну так себе удовольствие :) Прям очень на любителя. Если в обработке запроса забудешь о том, что надо все делать максимум асинхронно, теряется связь с клиентом.
Дело ж не в том, хайлоад или нет или сколько там пользователей или сколько оно приносит денег.
Если мой личный сервис, не зависимо от его популярности, упадет пока я буду спать, то проснувшись я испытаю лишь некоторый дискомфорт и чувство неловкости.
Если упадет сервис моего работодателя по моей вине, то уровень ответственности предполагается немного иной. Как минимум серьезные муки совести.

В ноде тоже можно случайно где-то воткнуть блокирующее чтение файла:)
Видимо у вас нет личных сервисом приносящих что-то существенное :) Потому как если оно упадет внезапно утром, то подскакиваешь пободрее, чем если это проект работодателя :)
моё пока в процессе развития:)
У меня SMPP-сервер в продакшне на ReactPHP. Вакансий нет — он написан и работает ))
И где?) Где статьи, где хвастовство?)
Чтоб народ видел, что вот у нас на PHP тоже можно асинхронно, и ничем не хуже других, а будет еще лучше.
Тему то надо популяризировать)
Я один раз оставил комментарий о своей любви к асинхронному коду, но получил пачку минусов. Больше я так не рискую :-) Надо статьями, да, но там пока ничего интересного нет. Будет интересное — напишу.
У меня для вас отличные новости, у нас открылась вакансия. Решили перейти с ReactPHP на AMPHP.
Найти можно на hh.ru по запросу amphp — на данный момент в списке будет только наша компания =)
Вот поэтому и нет вакансий, потому что минусы молча ставят xD

это не я, честно :)
увы, на hh.ru ничего не находит. правда, я и не ищу сейчас работу :) однако, большое спасибо, что помните меня.


но я считаю, что не зря переходите — на amphp писать гораздо проще и приятней. ну и они вполне адекватно относятся к пуллреквестам, если чего-то нехватает — даже я умудрился маленький апдейт протащить :)

Есть пара моментов, которые слегка раздражают. На следующей неделе будем думать над решением:
1. PhpStorm отказывается понимать тип данных, если он указан как "@return Promise<CommandResult|ResultSet>" (так например сделано в amphp/postgres). Вероятно должен быть плагинчик, поищем.
2. Если забыть сделать yield или rethrow, то exception потеряется. Опять же нужна инспекция. Кажется можно расширить Promise и в момент __destruct проверять осталось ли что-то внутри и если осталось, то у нас скорее всего проблема. Но это уже рантайм, хочется раньше.

Кстати из того что уже точно понравилось — постгресовый драйвер. Умеет всё что нужно и ровно так как это хочу видеть я. Варианты на reactphp не нравились все.

PS: Не знаю как у вас не ищется. Возможно дело в регионе. В Москве открываешь сайт, вбиваешь в поиск «amphp» — находит две вакансии и обе наши )

насчёт второго пункта — https://github.com/amphp/amp/blob/master/examples/exceptions/uncaught-with-error-handler.php должно помочь, с тайп-хинтингом в шторме, увы, не подскажу, но сами они используют psalm и он, вроде, понимает такие аннотации, как вы приводите в пример. насколько к шторму прикручивается как language server — не знаю, но как минимум прикрутить к каким-нибудь github actions вполне получится.


да, вы правы — я почему-то подумал, что поиск по всей РФ найдет, а когда не нашло не стал гадать с регионом) правду говорят, если в интернете пишул улицу без указания города — это москвичи :)

По второму пункту не совсем подходит решение, буду ловить в рантайме __destruct и проверять, но всё равно спасибо. Кроме того это опять же рантайм, хочется на уровне плагинов к шторму.

По моим ощущениям — недоитерированный промис чреват утечками памяти.

У меня тоже кое-что на ReactPHP работает, но это писалось давно :-)
С некоторых пор все подобное пишу на node.js/Typescript/NestJS — удобнее и практичнее.

Я не очень понимаю, зачем натягивать сову асинхронности на глобус синхронного PHP? Почему просто не взять NodeJS или Go или что вы знаете с поддержкой асинхронности? Какая цель конечная? Если «обучение» и «поиграться» — еще могу понять

Глупый вопрос.
Асинхронность — это фича следующей ветки php.
Будущее, иными словами...

тогда бы уж лучше горутины (именно ГО) с каналами взяли от Go, они как поновее чем EventLoop. Вопрос конечно останется за тем будут ли они в реализации Php такими же легковесными чем в Go. Я могу ошибаться, но EventLoop -ом в этом случае становится системный планировщик задач

нет все таки управляются Go
Горутина — это многопоточный eventloop в едином адресном пространстве, если очень грубо упростить до сути. Она имеет плюсы как плюсы (в виде утилизации всех ресурсов сервера с одного экземпляра приложения), так и минусы (магии не бывает, при многопоточной работе в одном адресном пространстве — нужно не забывать про конкурентный доступ).

Прежде чем говорить об аналогичной реализации для PHP — нужно решить проблему работы с тредами в PHP (когда я последний раз пытался в pthreads — весь мой рантайм состоял из сегфолтов, не очень хорошо знаю как обстоят дела сейчас). И нужно понимать, что одно не исключает другого — запускаем N машин и учим уже имеющийся планировщик распределять между ними задачи, кажется этого вполне достаточно.

При правильной организации потоков данных можно не прибегая к горутинам получить все плюсы и никаких минусов. Просто запускаем N экземпляров PHP (машины горутин) и распределяем между ними задачи (проксируем http-запросы, шарим сокет, разбираем очередь — не важно). Это покрывает почти все кейсы.

Прошу меня поправить, если я упустил какие-либо существенные различия — я не программирую на Go.
— — — — — — — — — — — — — —
Если предлагать что-то действительно мощное, то интереснее выглядит модель акторов, как в Erlang. Это позволит не только утилизировать все ресурсы одного сервера, но и все ресурсы всех ваших серверов. Но опять же строиться это будет снова на eventloop, никуда от него пока не уйти.
И вопрос глупый и я тупой, но может вы мне скажете, откуда вы взяли это
Асинхронность — это фича следующей ветки php.

Ваши домыслы и хотелки каких-то отдельновзятых разработчиков? Или есть какой-то пруф? Я пропустил момент, когда приняли соответствующий RFC?
Асинхронность — это фича следующей ветки php.
Будущее, иными словами...

Асинхронность — фича PHP ещё с версии 5.5, когда появилась возможность корутины через генераторы реализовывать (Статья от Никиты 2012г.).

Ну и проблема то не совсем в отсутствии инструментов, а в том что готовая экосистема под асинхронность не заточена никак и разработчики к её менять не готовы(не нужно оно им, и сложно).

А так — Amp / Swoole / Reactphp и их библиотеки вместо существующих фреймворков/ORM/большинства либ и можно дела делать.

И да, упомянув что для асинхронных программ нужно отказаться от занчительной части экосистемы, включая часть встроенных в php-функций и модулей не умеющих работать в неблокирующем режиме, вопрос целесообразности выбора PHP для таким программ становится актуальнее.

Spoiler header
Хотя что golang что nodejs я лично вряд ли бы выбрал

Фича пхп — это отсутствие порядка и отсутствие принуждения к нему кодеров (следствие: очень низкий порог входа и идеально подходит для того чтобы супербыстро сделать какую-нить халтуру, даже если вы знаете и другие языки).


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


вопрос целесообразности выбора PHP для таким программ становится актуальнее.

Но есть инерция, благодаря которой всё происхдит как есть.

Кому надо, тому инерция не мешает. Когда проект внезапно вырос до команды в 50 человек, хочешь или нет — нужен порядок.

Инерция мешает перейти на язык, где всё это изначально и нативно есть. Ну представьте, у вас 50 (а может 1000) пхп-кодеров в штате, решили вы сменить язык на более подходящий. Это ж будет куча затрат (не только непосредственно финансовых) на реорганизацию, найм новых программистов (да и где их взять столько разом?), переписывание движка. Или представьте побочные эффекты от новостей вида "авито уволило свой штат пхп-программистов в полном составе и ищет новых на другом языке" — тоже может негативно сказаться на репутации. Можно придумывать какие-то плавные переходы, но всё равно это всё расходы и не совсем быстро. В долгосрочной перспективе это всё конечно окупится, но до неё надо ещё дожить, а в краткосрочной могут быть большие проблемы. Вот и продолжают дорабатывать то что есть.

Тут вопрос стоит скорее так "Есть современный PHP, который позволяет поддерживать порядок почти на том же уровне, что и Java/C#/Typescript/что-там-ещё, и есть наша кодовая база в N миллинов строк на нём. Как скоро окупится перевод её на новый язык ради небольшого улучшения порядка, учитывая все расходы и потери типа репутационных на рынке труда"

> зачем натягивать сову асинхронности на глобус синхронного PHP?

Так ведь и JS таким был. И NodeJS тоже был такой совой, которую натянули на синхронный js.
Лично по моему мнению, в PHP это выглядит красивее, чем в JS, потому-что php изначально был рассчитан под бэк, а js под фронт.
Отсутствие асинхронных библиотек — вопрос времени.
в PHP это выглядит красивее, чем в JS, потому-что php изначально был рассчитан под бэк, а js под фронт.

А как вы себе представляете синхронный однопоточный фронт? Рисуешь дурацкую анимацию и все остальное заблокировалось? Интересно) Почему на беке изначально для вас асинхронность кажется более естественной? Не уж то потому, что вы php-разработчик?) Я вас успокою, я тоже PHP-разработчик, но мне даже близко асинхронность в PHP не кажется чем-то «более естественным»

так ведь и JS таким был. И NodeJS тоже был такой совой, которую натянули на синхронный js.

Не подскажите когда именно? Не поделитесь пруфом? А то я все никак не пойму — чего это мы всё коллбеки колбасили в нулевых, раз все синхронное было
PHP это язык-интерпретатор. Он читает код построчно, переводит в свои инструкции и выполняет.

Что-то мне кажется, что это сейчас не совсем так. Что на самом деле PHP прекомпилирует весь код до начала его исполнения.

PHP не может прекомпилировать весь код просто по факту возможности написать вот такое
if ($foo !== null) { $bar = require "$foo.php"; }
Да, там есть опкэш, да, предзагрузка, но по факту PHP все еще остается интерпретатором, в котором можно прямо в рантайме собрать строку с кодом и заeval'ить
PHP поддерживает разные подходы. Некоторые из них будут работать быстрее. Подход с eval и постоянными require — будет работать медленнее.

В PHP8 планируется JIT, по идее скорость работы может сравняться с V8. И да, в JavaScript так же есть eval.
Отсылку к JS честно не понял, поясните. Он же тоже интерпретируемый и в нем так же можно делать условные динамические реквайры.
Я отвечал на тезис «на самом деле PHP прекомпилирует весь код до начала его исполнения»
Виноват, немного упустил контекст, но по своей сути мой комментарий не меняется. Код действительно компилируется до начала исполнения (вернее будет в PHP8), для этого есть preload. Но никто не мешает игнорировать современные подходы и тыкать eval, чтобы было медленно :-)
Мне казалось, что JIT — это не предкомпиляция, а комплияция во время работы (just-in-time, о чем собственно говорит название). Но могу ошибаться, не погружался в эту тему никогда
Да, но в комплекте с preload — это вполне себе предкомпиляция. Те файлы которые вы укажите — будут скомпилированы до начала работы.
Тут согласен. Однако согласно этому бенчмарку прелоадить все менее выгодно, чем прелоадить hot classes. Но я в целом понял, что вы пытаетесь донести, я бы только сформулировал это по-другому

PHP (8) можно использовать как полностью компилируемый язык при желаниии.

Однако, мне кажется, большинство современных приложений далеки от этого. Даже тот же symfony использует динамический require в своем коде. Но благо в версии 4.4 они завезли генератор прелоадинг конфигурации для контейнера
По ссылке говорится, что hot classes — это файлы закэшированные opcache. Он кэширует все используемые файлы. Логично, что подгружать только используемые файлы даёт лучший результат, чем подгружать все файлы.

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

Я кстати как раз на днях написал код с динамическим require. Но обычно я так не делаю. Если говорить про reactphp (вспоминаем о чём топик изначально) — кажется там нет таких проблем.

Preload — это, видимо, загрузка файлов до выполнения require.
А прекомпиляция — это разбор структуры файла и преобразование ее в байт-код до исполнения. Исполнение идёт уже по байт-коду.


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

Он его прекомпилирует в некоторых случаях, но это просто оптимизация, а по сути языка он интерпретатор. И останется таким даже после релиза JIT в самой популярной реализации :)

А где проходит водораздел между компиляторами и интерпретаторами?
В явном шаге компиляции?
В динамическом импорте?
В преобразовании исходника в машинные инструкции?
В построчном исполнении исходника?

Нужно различать язык и конкретную реализацию транслятора языка. PHP и JS — интерпретируемые языки, самые популярные трансляторы которых активно используют компилирующие техники под капотом.

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

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


Сейчас, наверное, нет популярных чистых интерпретаторов (что говорить, BASIC-MICRON для i8080, на котором я начинал писать в 80-х, уже не хранил чистые исходники программы, а токенизировал их, храня и интерепретируя уже байт-код виртуальной машины) под капотом, но в интерпретируемых языках трансляции происходят под капотом по умолчанию и это деталь реализации.


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

А есть большая разница в том, сохраняется ли "другой набор команд другого языка" в файле или в памяти?

Есть. "другой набор команд другого языка" можно запускать на машине, где исходного языка нет. Хотя, конечно, можно в бинарник упаковать и исходный код, и интерпретатор, но это просто архиватор специфический.

"другой набор команд другого языка" можно запускать на машине, где исходного языка нет.

Но есть VM для этого "другого языка". С некоторой натяжкой, PHP+opcache можно считать такой VM.


PS Ни слова про eval! :)

Вот именно, с натяжкой. Просто оптимизация конкретного интерпретатора. Файл с опкодами получить и запустить не то чтобы невозможно, но очень нетривально.

Да не то, чтоб нетривиально на самом деле.
Но я про то, что PHP, при совсем небольшой доработке напильником, начнет полностью удовлетворять вашему определению компилируемого языка. Другой вопрос, кому это нужно?

Это, скорее, дефолтный его транслятор станет удовлетворять моему определению компилятора. :)

Event Loop. Есть шанс, что он появится, потому что ведется работа над тем, чтобы внести Event Loop в каком-то виде в ядро.

есть пруфы?
Попробовал проверить вставку 100/10000 записей с помощью pdo и amphp, пдо оказался ровно в 2 раза быстрее, практически самый простой код, понятное дело что скорее вего будет выйгрышь на параллельных тяжеловесных операциях, но в целом асинхрон не всегда в плюс…
Сомнительное утверждение. Если не трудно — выложите на гитхаб, мне было бы интересно проверить воспроизводимость.
возможно код не самый оптимизированный, но максимально простой и похожий, из примеров, до этого не работал с асинхронными библиотеками, может чего-то упустил
github.com/asmdk/ahphp_db_compare

Оба insert*.php — синхронный код, но в варианте на Amp дополнительные накладные расходы на event loop и amp-инфраструктуру. Ещё и loop в тестах наверняка через select, иначе бы сложно было заметить разницу.

не знаю насколько вы были правы, т к весь код был из примеров асинхрона, в любом случае сейчас немного поправил код, и он скорее всего выполняется асинхронно, т к поля инкремент в базе и в пхп не совпадают, до этого совпадали в обоих вариантах с пдо и с ahphp, что в принципе ожидаемо.
Но время выполнения не изменилось, я бы даже сказал увеличилось на 5-10%

Сейчас, с массивом promises — "типа" асинхронный, но это ничего не даст, потому что все равно в СУБД будет tail lock и по факту все запросы выполнятся последовательно.


Пишите хотя бы в разные таблицы, чтобы разницу увидеть. А то вы измеряете поведение реализации версионности в СУБД на разных вариантах нагрузки. :)


А вообще тестировать надо не это. Тестировать надо асинхронную обработку нескольких запросов пользователей. Например, 1000 пользователей одновременно отправляют некий REST-запрос. При этом многие из них на медленном мобильном соединении. Вот тут увидите настоящую разницу.

да, спасибо что подметили, действительно если писать в 2 таблицы или более разница в 1.5-2 раза в пользу асинхрона, т е получается в нем есть смысл при большой записи в несколько таблиц…
Вы неправильно понимаете асинхронное программирование.

insert*.php — забудьте, преимущество eventloop становится очевидным при работе с несколькими потоками IO.

translate* — для amphp вы делаете семафор на 10 потоков, а в curl_multi используете 100 потоков. curl_multi предоставляет так же асинхронный IO, поэтому использовать его в качестве синхронного примера — нельзя.

Простой пример задачи — вам нужно вывести на странице информацию собираемую из десяти баз при помощи медленных SQL-запросов. В качестве медленного запроса — можно использовать SELECT SLEECT(10). При блокирующем IO вы будете отправлять эти запросы последовательно, при асинхронном — параллельно. Время получения конечного результата в синхронном режиме = 100 секунд, в асинхронном = 10 секунд.

amphp, reactphp (и даже curl_multi*) — это лишь инструмент для асинхронной работы с IO. В зависимости от задачи выбирается и инструмент. Подключая полноценный асинхронный фреймворк — вы, в том числе, избегаете побочных эффектов, если один IO-поток подвис — остальные продолжают работу.

Позволю себе вмешаться.


Поток в php всегда 1. И в традиционном, и с помощью amphp
Код выполняется не параллельно, а конкурентно. Разница в словах маленькая, но существенная в деле

io stream не имеет отношения к количеству threads. pthreads никто не отменял (хотя это выходит за рамки дискуссии). amphp и традиционный php — это один и тот же php, amphp — фреймворк.

Насчёт параллельно и конкурентно — согласен. Я имел в виду, что запросы будут исполняться параллельно (разные ж базы), в следствии конкурентной отправки через IO (но написал «отправлять» вместо «исполнять», ошибочка, да).

традиционный — это просто способ подчеркнуть что имеется в виду)
pthreads умер давно, да и не нужен он :)

На смену ему пришёл parallel, действительно.

В зависимости от задач, некоторые cpu-bound задачи будет удобнее решать. С тредами можно сделать те же горутины, про которые здесь писали.

Для cpu-bound есть воркерпул у того же ампа. Процессы проще и надёжнее :)
Что касается горутин, то вас не туда понесло)

Вы допускаете ту же ошибку, что amsdk. Есть разные задачи и разные подходы, не нужно зацикливаться.

Процессы проще ровно до тех пор, пока вам не нужна быстрая общая память. shmop не предлагать, поверх него придётся заново писать все базовые структуры.

Горутина — тот же eventloop, имхо. Не понимаю, почему вы считаете что это «не туда». amphp даёт плюс только на io bound, горутина даёт плюсы на cpu bound при том же синтаксисе. Удобно же.

это как раз вы на те же грабли прыгнули :)
Я бы на вашем месте посмотрел чем Горутины отличаются от условных Корутин.


p.s. не только 1 буквой из соображений маркетинга.


Что касается межпроцессного взаимодействия, то в пхп нет ни единого юзкейса для этого

golang.org/doc/faq#goroutines
Goroutines are part of making concurrency easy to use. The idea, which has been around for a while, is to multiplex independently executing functions—coroutines—onto a set of threads. When a coroutine blocks, such as by calling a blocking system call, the run-time automatically moves other coroutines on the same operating system thread to a different, runnable thread so they won't be blocked. The programmer sees none of this, which is the point. The result, which we call goroutines, can be very cheap: they have little overhead beyond the memory for the stack, which is just a few kilobytes.
Что касается межпроцессного взаимоджействия, то в пхп нет ни единого юзкейса для этого.
У вас нет, ок. У меня другие задачи.

Ни у кого нет.
И вы всё ещё не понимаете почему Горутины, а не Корутины.


Эт бывает

А вы не думаете :)
Там есть ответ, но вы явно не очень понимаете как работают рутины в прочих языках и в чём отличие именно в голанге (в сабже есть).

Что касается межпроцессного взаимодействия, то в пхп нет ни единого юзкейса для этого

Разделяемый локальный кэш, например, часто хотелось бы иметь из коробки. И более удобно чем shmem и ко

Недавно с Лисаченко аккурат на эту тему общались.
Он хочет реализовать в рамках своих либ, решая определённую проблему, но делает это не с того конца. Формально, он сам себе эту проблему создал :)

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

По поводу вашего примера либо он не очень информативен, либо так никто делать не будет. У меня будет на странице 10 аякс запросов, и при выполнении каждого я уже увижу эту информацию на странице, я не буду все делать в одном запросе, даже при наличии асинхронности это не очень удобно, в вашем же случае итоговый результат все равно будет ждать выполнения самого медленного запроса, чтобы все это потом отрендерить.

"асинхронность другого типа"


Заканчивайте, не смешно уже.

кстати написав код, на отправку 100 запросов на яндекс трансдейт апи, и намеренно добавив задержку в 0.25 сек к каждому запросу, а потом инсерт результатов в базу, ожидаемо асинхрон выполняется примерно в 1,5 раза быстрее.
но если задержку не добавлять, то асинхрон примерно раз в 7 быстрее…
опять же оказалось не все так радужно, заменив код в синхроне на многопоточный curl (curl_multi_exec), он оказался быстрее асинхронного варианта примерно в 2-2.5 раза, все файлы доступны в репе выше, нужно всего лишь подставить свой яндекс апи кей, который можно получить бесплатно…
Чтобы не было недопониманий, опишу свою позицию, я не против асинхронного кода, но в моей практике было немного зачад, где асинхрон действительно можно было бы применить и он давал ощутимый прирост, но я уверен случаи его использования есть, но скорее их не так много, как синхрона. Также я вижу немного основных недостатков асинхронного кода:
1. Он не всегда быстрее
2. Сам код менее понятный и простой
3. Более сложен для дебага
4. На данный момент требует дополнительных библиотек

ПОэтому ради присроста процентов в 10, если это не очень критичный к производительности код, учитывая все минусы я бы не использовал асинхрон, лично мое мнение, никому не навязываю…
  1. Он всегда быстрее, если вопрос касается I/O задач.
  2. Он остаётся таким же понятным и простым, добавляется лишь ключевое слово yield/yield from. В остальном никакой разницы
  3. Да, xdebug не дружит с корутинами. Но это проблема не только php
  4. pdo — тоже дополнительная библиотека. Равно как и всякие dbal'ы

p.s. Вот вам немного синтетики: https://github.com/php-service-bus/performance-comparison#details
то, что выше — криво, косо и не показательно.

1. Понимаю что скорее придирка, но все же, если мы возьмем гипотетический пример дисковой операции, в которой в синхроне у нас файл пишеться с максимальной скоростью на диск, то в асинхроне вы не получите никакого прироста, даже наоборот.
Ну и я привел найболее частые операции: это работа с базой и отправка хттп запросов. В первом случае у нас профита никакого нет, во втором он есть, но в пхп из коробки есть скажем так асинхронный курл, поэтому надобности в дополнительных библиотеках нет.
2. По мне даже на простом примере видны небольшие отличия, на реальном коде их будет еще больше, но ок, пусть будет на любителя.
3. Мой посыл был в том, что учитывая этот минус, надо думать, а стоит ли оно того, а не думать, ну раз везде так, значит надо использовать.
4. имелось ввиду, что пдо есть из коробки, а чтобы исп возможности хотя бы пдо в асинхроне, нам надо установить amphp/amp и amphp/mysql

p.s. на самом деле синтетика плюс минус такая же, просто у человека было больше времени и он оформил код получше и с исп ооп, но работа с той же базой, на том же уровне и он навесил очень много операций и сложно судить что именно ускоряет. Не могу утверждать, но могу предположить что прирост именно за счет асинхронной работы с очередями, сообщения быстрее добавляются и быстрее обрабатываюся. Исходя из этого можно сделать вывод, если у вас паблишится десятки тысяч или даже сотни тысяч соообщений в час, вы получите более менее неплохой прирост, если же пару тысяч в сутки, то не имеет смысла…

Проблема в том, что вы абсолютно не понимаете, как работает конкурентный код. для вас всё — асинхронность, что не совсем верно (в корне не верно). Но пойдём по порядку.


  1. Разница будет видна и на 1 записи, и на 10 разом. В обоих случаях запись не блокирует общий поток выполнения и во время записи можно сделать что-то ещё.
    Мультикурл будет блокировать поток выполнения и работает совершенно иначе. Но мы уже выяснили, что вы не очень понимаете разницу. Что касается вашей демонстрации, то там просто код неверный. А не "PDO быстрее"


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


  3. Ничего не понял, но звучит круто


  4. Ну это ведь всё меняет! Пойду на авторов bc-math пожалуюсь. А то иш чё удумали, из коробки нету, кафно.


  5. Практически всё, что дальше после 4-ого пункта — мусор, который к реальности отношения не имеет и комментировать его нет смысла.


1. Я понимаю, но я написал код который хоть немного приближен к большинству реальных задач, ваш посыл я понял, если мне надо будет выполнить 1000 хттп запросов, потом 100к инсертов в базу, не зависящих от этих запросов и потом посчитать какую-то сложную логику, не зависящую от всего вышеперечисленного, то запустив это асинхронно я получу прирост, это конечно да, но где вы такие задачи видели? не говоря уже о том что если они не зависят друг от друга кто их будет синхронно запускать? я не говорю что их вообще нет, просто их процент очень мал…
2. я согласился что тут на любителя
3. имелось ввиду то, что при выборе писать асинхронно или нет надо учесть что будут проблема с дебагингом, не важно что это и в других языках, конкретно на твоем проекте они будет, и стоит ли тот прирост производительности если он будет, отсутствия дебагинга.
4. Дело не в том что если нет из коробки это кафно, а в том что когда есть из каробки намного удобнее. Меншее количество сторонних библиотек тоже плюс. Тем более многие крупные компании не любят внедрять сторонние библиотеки, очень сложно с этим, но даже если внедряют, то берут определенную версию, ложат себе в репу, какой нибудь отдел инф безапасности все это проверяет, и потом исп новые версии будет не так просто. Это все в целом явл минусом, но не для всех

В целом мой посыл что асинхрон это хорошо, но в реальных проектах не много где применим, и уж тем более проектов где прям все писать асинхронно, еще намного меньше…
  1. Вы не разобравшись в сабже написали тест и сделали это ожидаемо хреново. Ещё раз: оно медленнее только потому, что неправильно написано.
  2. Ничего смертельного в отсутствии xdebug нет. Научит вас логи нормальные писать :)

...


  1. Просто потому, что пхпшников, которые умеют в конкаренси код, единицы. И все они пишут на более "взрослых" языках.
1. Как вы можете судить хреново я сделал тест или нет, если вы даже не удосужились понять что я тестировал. Тестировал я определенную задачу, а не пытался написать код при котором асинхронный вариант будет быстрее. И как подметили выше, при добавлении данных, пусть даже множеством запросов одну таблицы я прироста не получу, надо взять хотя бы две, что я проверил и убедился если взять 2-4 таблицы, то асинхранный код получается в 1.5-2 раза быстрее, из этого я могу сделать вывод что если мне надо добавлять много данных в одну таблицу в асинхроне нет смысла, в 2 и более, стоит задуматься, но тут тоже не все так просто, но здесь хотя бы есть смысл рассмотреть асинхронный вариант

2. Вы не можете писать логи на все, в больших приложениях они будут в сутки генерировать гигабайты информации, зачастую даже агрегаторы логов просто не смогут их нормально отображать, более того у вас не всегда может быть прямой доступ к файлам логов (аггрегаторы не в счет) и придеться постоянно у кого то просить тебе его сбросить, ну и копаться в гигабайтных файлах, такое себе удовольствие. Ну и все равно на все логи не напишите…
  1. Фигню тестировали ради тестирования.
  2. И в этом самом больше приложении на проде вы xdebug'ом всё найдете, да.
    Что там за агрегаторы логов, которые не могут отобразить — ток в епаме известно
Когда человеку нечего сказать — он переходит на личности, епам — это в большинстве своем аутсорсовая компания, погуглите что это такое, вкратце мы пользуемся теми сервисами и технологиями, которые предоставляет заказчик, агрегатор логов подключен к десяткам проектов, которые в сумме генерят, может и террабайты информации, поэтому в логах мы немного ограничены, возможно все это связано и с расходами, утверждать не буду, т к этим занимаются другие команды и у нас туда очень ограниченый доступ.
Что качается xdebag'a, я сам не понял каким боком логи его заменяют, но это были ваши слова
В общем я так понимаю дискусии у нас с вами не вышло, удачи и будьте немного сдержанее…

Вспомните контекст, поймёте.
Речь идёт про отладку конкурентного кода и то, что в реальности она не особо сильно отличается от обычного.


Что касается агрегаторов, то условные elk\efk\graylog без проблем справятся с любыми объёмами при прочих равных. Они их разом, если что, не отображают. Впрочем, вы всем этим явно не пользуетесь.

Sign up to leave a comment.