Pull to refresh

Comments 184

Рад слышать, что проект развивается.

Вопрос по этапу оптимизации. «безопасно заинлайнить простые функции» — это про php код? А почему не отдать такие оптимизации всецело в руки с++ оптимизатора? Или есть какие-то граничные случаи, когда он не видит, что можно заинлайнить?

И ещё вопрос по организации работы между командами. Вот я написал какой-то php код, компилирую kphp и у меня ошибка где-то на уровне g++. Что вообще происходит в этом случае? Сразу запрос в вашу команду (aka ошибок с++ не должно быть) или разработчик сам разбирается?
Про заинлайнить — на самом деле g++ и инлайнит :) А вот прикинуть, какие функции при кодогенераци разбивать на cpp/h, а какие помещать в h с пометкой inline или __attribute__((always_inline)) — это уже KPHP решает. С LTO на десятках тысяч функций там всё не совсем гладко.

Про ошибки на уровне g++ — по-хорошему, конечно, их не должно быть, они должны отбиваться на уровне трансляции с разумной ошибкой. Но в каких-нибудь редких неучтённых сценариях проскакивают — и тогда, обычно, да, PHP-разработчики приходят в наш чат :)

Не хватило зралищ страшных цифр: во сколько сотен тыс. строк C-кода всё это транслируется, сколько тысяч файлов, сколько ГИГ-ов несжатый бинарник выходит 😀

FAQ.


Q: Что такое "движки"?
A: s/движки/сервисы/ (или "демоны") — сервис сообщений, сервис лайков, etc.


Из статьи:


Например, нельзя обращаться к полям по имени или вызывать так методы.

Q: А как происходит обращение к полям из KPHP?
A: По именам, но без динамических выражений.


$this->field // ok
$this->$fieldname // not ok
Это всё занятно, но остальной мир переписывает проекты на Go, Java, .NET, чтобы была типизация и скорость. А вы изобрели велосипед, причём в одном колесе нет половины спиц, а второе квадратное.
Я наверное что-то не понимаю, но куда уж быстрее чем C/С++?

Имелось ввиду переписывает проект, который изначально на PHP. До изобретения KPHP.

А. Полагаю что ресурсы не те, чтобы весь код переписывать полностью на другой стек. Они же нынешний PHP транслируют в С, в этой ситуации и правда легче транслятор написать, чем переписывать все. В свое время для PHP было куча трансляторов, там реально несложно, достаточно просто нормально распарсить PHP и на основе его кода генерить аналогичный код на С, тем более там много похожего.
Это как писать. Мне пришлось как-то переписать проект в ~20 килострок с С++ на Java буквально путем переименования исходников и построчного приведения их в компилируемое состояние. При этом, к всеобщему удивлению — производительность выросла раза в 2 (и на x86 и на SPARC). Это не было критично для проблемы, которую я пытался решить — поэтому профайлингом не занимался, но скорее всего выигрыш был получен за счет более эффективной реализации библиотек.
Ого! Нет, на самом деле тут смотря с какой стороны посмотреть, С/С++ это по сути конструктор, и на них можно писать как угодно, я уж не говорю что сборщиков мусора из коробки в них нет, поэтому парадокс может быть в том, что сам сборщик даже может являться проблемой, поэтому считается что самый быстрый он в идеальных условиях и когда руки тем местом вставлены, а если нет — то его даже PHP может уделать спокойно :D

Это в какие годы было?

Ниже уже ответили, 10 лет назад, или даже больше, тогда по какой-то причине вдруг пошла мода на компиляторы для PHP, и ладно CLI, но компилили даже GUI, была даже своя IDE, написанная полностью на PHP (!). Я даже больше скажу, были не просто трансляторы в С, а полноценные трансляторы в байт-код PHP (!!). К сожалению, эти проекты ныне мертвы. Нет, они работают, почему нет-то, даже ООП поддерживают, только никакие плюшки современного PHP не поддерживают, увы, а он очень изменился за эти десять лет.

Я наслышан, что году в 14 один наш русский разработчик взялся облагораживать php, запилил оптимизаций, причесали API, чтоб единообразным было, избавились от PAAMAYIM NEKUDOTAYIM и прочих еврейских словечек в ошибках и с тех пор живут не хуже python. Собственно, С++ с тех пор тоже шагнул, но до 11 стандарта STL был в не очень удовлетворительном состоянии, поэтому каждый норовил отказаться от стандартных контейнеров и реализовать свой костыль. В 2010 году cxx11 ещё не рождён комитетом, и перегонка с плюсов в java действительно могла дать ускорения. Не уверен, правда, что 2х, но на "бенчмарков нет" и суда нет.

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

Вот-вот зарелизится PHP 8.0 с JIT-компиляцией в нативный бинарный код. А практически полноценная компиляция в байт-код (опкод в терминах PHP) уже много лет из коробки — компилируется один раз и байт-код кэшируется. Единственное, нет из коробки компиляции во что-то типа .pyc файлов, чтобы скомпилировать на CI и прямо файлы с байт-кодом разворачивать на сервере. Но люди экспериментируют с такой моделью.

Ооооой, дааа, дааа, и не говорите, все конечно ждут полноценную JIT, а не мутный Zend Engine, я сам не знаю что из этого по факту выйдет, поэтому особых эмоций по этому поводу пока стараюсь не проявлять, а так конечно же жду, что уж греха таить) Вообще удивительно конечно, столько даже за последнее время появилось языков, поддерживаемых в том числе и корпорациями, но при этом только PHP разрабатывается так активно, что я даже как разраб на нем почти с 10-летним стажем перестал следить, знаю просто что новые версии часто выходят, иногда переезжаю, и все) И это при полной совместимости с лютым легаси, очень давно переезжал с 5.3 на 7.0, лег как влитой, даже пришлось в phpinfo проверять версию на сервере, чтобы уж наверняка. Понятно что изначально все писалось правильно и без deprecated, что-то еще пришлось конечно подлатать, но сам факт)

Только Никита не русский, если что… А сабж говорил скорее всего про Диму.

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

Так можно определить "российскость" в первом приближении, а не "русскость", гражданство, а не национальность.

У меня дети родились и живут в Чехии — это значит, что они чехи?

Я просто написал, что Никита немец. Это довольно популярная ошибка считать что он русский, т.к. и имя и фамилия у него "наши" и более того — он знает русский язык.


В основном Никита занимается новыми фичами языка и причёсыванием поведения и внешнего API. За оптимизацию и производительность же отвечает Дима, как и за внутреннее API (i.e. Zend). Именно благодаря работе Стогова и появилось новое ядро 7ки и JIT в 8ой версии языка.


Так что говоря о производительности, унификации ядра и упоминая о том, что "разработчик русский" — имелся ввиду скорее всего именно Дмитрий, а не Никита. Именно это я и написал. А вы тут устроили какой-то холивар на почве религиозных войн, чесслово))

UFO just landed and posted this here
а разве компилятор не умнее всех этих человеков? ну в плане генерации оптимального ассемблера?
UFO just landed and posted this here
Это понятно, я-то говорю о человеко-понятных языках) Но тут тоже как посмотреть, тут есть товарищ один, который написал целый форум с нуля на чистом ассемблере (правда странно как-то, что тут после этого ни разу не появлялся, хотя форум на ассемблере написал, ну да ладно), но говорит что не самая быстрая скорость у него, но я полагаю что там что-то со сборщиком мусора — либо корявость, либо вообще его отсутствие.
А зачем все это, когда есть PeachPie?
www.peachpie.io/tag/wordpress

В DotNet со временем появится компиляция в Native, она и сейчас есть неофициально, так называемый Mono AOT и .NET native.
Пользовался я им, до сих пор сыроват, плюс надо вручную ходить по всему проекту, собирать инклуды и вписывать их в конфиг перед сборкой. Для крупных проектов это неприемлемо.

P. S. Минус не мой, но я полагаю это потому-что речь идет о С, а вы предлагаете .NET, ибо их как-то неприлично сравнивать.
Ну да, средне между С и Явой, это же предсказуемо) Плюс отсутствие кросс-платформенности, что реально на нет все сводит. Они что-то там экспериментируют с ней, но это все эксперименты пока.
Экспериментируют LOL,

www.linux.org.ru/news/opensource/15994444
Компания Microsoft выпустила .NET 5 для операционных систем Windows, macOS, Linux.

.NET 5 — единая open source платформа, объединяющая .NET Core, .NET Framework, Xamarin и Mono, позволяющая использовать единую кодовую базу решений для всех платформ, включая Android и iOS.

существенно улучшена производительность и уменьшено потребление памяти
Казалось бы .net core уже года 4 существует, а всё ещё есть люди, которые воспринимают .net, как чисто виндовую технологию.

А куда мы деться могли? Вымирать нам ещё рановато.) А mono хорошо помним ( А все гайды и туториалы C, попадающиеся на глаза, начинаются с чего-нибудь вроде "Напишите helloworld.cs в блокноте… Первая учебная программа готова, а теперь начинаем нормально работать: создайте новый проект в Visual Studio...". В общем и в целом поддержка Linux в экосистеме .NET выглядит со стороны как "Вы знаете и любите .NET, теперь вы можете попробовать сбилдить и запустить ваш проект под Linux, но просто это не будет".


Не похоже на то, чтобы кто-то был заинтересован в переводе проектов годами и десятилетиями, разрабатываемых под Linux и в Linux с той же Java под .NET. Я уж молчу про PHP, JS, TS, Ruby, Python

Вот кстати тоже ищу ответ на вопрос: а где место всему этому типизированному пхп? Он же доставляет нереальное количество боли и чем строже проверки тем больше боли.

Я бы еще понял если бы хоть ктото начал переписывать ext'ы для подключения к бд со строгой типизацией, дак нет этого.
Первое что пришло на ум — прилетело число вместо строки (например, array_search не нашла ключ в массиве, хотя должна была). Можно проверять конечно ее, но за всеми проверками не угонишься, а тут он сразу скажет воу, я жду строку, а прилетело число, почему? Изменился список аргументов в функции, а вы про это забыли (ибо имеете право), поэтому по старинке суете каким-то аргументом например строку, хотя уже давно этот аргумент должен принимать какой-то объект (например класс, или массив), представляете что будет на проде если он попытается из этого класса вызвать какой-то метод, а это и не класс, а просто строка, и это все на какой-то странице, которую могут отыскать только юзеры, однажды зайдя на нее. А тут даже до прода не дойдет, нормальная IDE обругает вас прямо на этапе добавления аргументов в функцию.
Зачем типизация я прекрасно понимаю, но в php нет дженериков, а без них типизированные коллекции доставляют ну просто уйму проблем, и пока их даже на горизонте не видать.

Объявление типов переменных тоже вроде еще не завезли, и если вы внутри функции инициализируете переменную а затем отдаете ее наружу вы запросто уже в рантайме получите TypeError если вдруг вернете не то что указано в декларации функции.

Полно милых вещей наподобие SimpleXMLElement, которые с типами работают ну крайне странно: смотришь — массив, по типу — массив, говоришь неси сюды — на тебе первый элемент.

Ну ок, то все происки зла, давайте возьмем Doctrine DBAL, взрослая штука, все знает, вот только все данные строковые, извольте гидрировать сэр. Хотя если порыться в недрах драйвера pg то он про типы вполне себе в курсе, просто забывает по дороге из-за этого работа с массивами или диапазонами пг превращается в увлекательное занятие.

Возвращаемый тип static вот в php 8 будет, тоже немало крови попил.

Я к тому что оно все клевое, спору нет, но если сразу перейти на яву то в нагрузку все это, плюс то до чего пхп еще расти черт знает сколько, плюс многопоточность и возможность писать нормальные приложения реального времени.
Ну дженериков нет, да, поэтому я представляю себе в уме коллекцию как JSON. Только вам вот зачем коллекция, почему бы банально не засунуть в массив объект, а там уже вызывать нужные методы и свойства (переменные) с нужными типами данных и на входе, и на выходе? По мне дак даже лучше дженериков (ибо методы). Я уж не говорю о том, что коллекции не всеми ЯП поддерживаются, в С их нет вовсе.

Ява хороша, спору нет, но не компилируема, увы, поэтому как по мне только под андроид писать.

P. S. Типы переменных в 7.4 уже поддерживаются.
Мы у себя используем библиотеку кодогенерации типизированных коллекций в php, не так гибко как с generics конечно, но в целом свою задачу решает.

Нельзя взять и переписать кучу легаси PHP-кода. Ну и компиляция в C++ подразумевает отсутствие явного языкового рантайма, кои присутствуют у всех трех вышеперечисленных.

Это делалось для того, чтоб не переписывать ВСЕ на Java/.Net.
И использовать тех же программистов.
И использовать тех же программистов.

Как будто что-то хорошее. Тем более KPHP не особо на PHP похож, так что переучиваться всё равно стоит.

Я задавал похожий вопрос товарищам из фейсбука когда они мне расказывали про HipHop, и задам его еще раз — кроме исторических причин (куча кода на PHP), есть ли преимущества перед реализацией продукта сразу на типизированном языке, с JIT или компиляцией в машинный код?


Аргументом, разумеется, является то, что "а вы знаете сколько у нас строк на PHP?!?". На мой взгляд, аргумент это довольно слабый: в конце концов, никто не мешает разбивать код на микросервисы, связанные RPC, и переписывать их по отдельности, начиная с самых критичных по производительсности (вариант: с самым загнившим кодом). В конце концов, те части, которые действительно проще написать на PHP, можно на нем и оставить — выполняя все performance-critical задачи в native code.

PHP8 — это уже и есть типизированный язык с JIT :)

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


Кстати про то что PHP 8 типизированый и JIT не знал — очень давно не писал на PHP, уже не в курсе что происходит в этом мире :)

PHP8 — это уже и есть типизированный язык с JIT :)

Ассерты в рантайме(а именно ими тайпхинты и являются) — не типизация. Ну или не статическая типизация, если вам такая терминология по душе, хотя в контексте kphp очевидно что речь не о «динамической».
Ну и по скорости PHP 8 по прежнему на порядок отстаёт(и будет отставать) от мейнстримных и не очень компилируемых языков.
Я пишу веб и микросервисы на PHP, на большинстве задач типа активной работы с базой, JSON и HTML, мой фреймворк обгоняет аналоги на Go / C# и идет вровень с Java / C++

Можете сами сравнить на свежих тестах Techempower (ищите comet среди конкурсантов)

www.techempower.com/benchmarks/#section=test&runid=10218082-6e18-4513-9be4-e721bb8a1596
правда? а уже есть драйвер для pg с поддержкой типов?
Имеется ввиду то, что pg сама по себе строготипизирована в отличии от мускула
mysql тоже типизирован, просто в угоду говнокодерам там до сих пор держат режимы совместимости типов.
Если честно, нет других причин кроме исторических. Как бы слабо ни звучал аргумент «у нас миллионы строк кода» и как бы пафосно сверху ни спускали мысль «давайте всё попилим на микросервисы» — реальность не такая. В реальности всё достижимо из всего, а цикломатичность кода стремится к бесконечности :)

Да, в первую очередь нужно приводить в порядок код. Независимо от того, бить на микросервисы или нет. Но по опыту скажу: те части, где нет Legacy и которые в порядке, они и на PHP очень даже стройно смотрятся. А с учётом того, что и по перформансу теперь быстро — то нам более чем подходит такой вариант.
UFO just landed and posted this here
Потому что он появляется вот только-только сейчас, а проблемы с производительностью мы решаем уже несколько лет? )

Я более чем уверен, что для наших задач мы всё равно будем значительно быстрее, уж слишком много сил для этого приложили и слишком много неочевидных моментов под себя заточили, которые не опишешь в статье.
Хотя не исключаю, что PHP 8 в синтетических случаях случайно может оказаться сравним.
Почему разработчики предпочитают создавать свой велосипед, вместо того, чтоб контрибьютить в PHP?
Может если приложили бы усилия для повышения производительности в PHP, jit появился бы на пару лет раньше и увеличил производительней языка. За следующие пару лет дооптимизировать jit до максимума производительности, и отпадет обходимость в использовании kphp и hiphop.

Я думаю, причина примерно та же, почему ФБ сначала реализовал транслятор в C++ — есть такое распространенное (и нельзя сказать, что необоснованное...) мнение, что никакой JIT не будет быстрее хорошего кода на плюсах. В случае с тем, как реализованы классы в KPHP, я лично сомневаюсь, что JIT в PHP в скором времени сможет догнать простой код на плюсах, который генерит KPHP, а усилий приложить придется намного больше.

Если почитать отчёты Фейсбука, почему они закрыли HPHPc в пользу HHVM, то там, в том числе, и проблемы с производительностью. JIT догнал и перегнал у них компиляцию, а как наращивать производительность у компиляции они придумать не смогли.


Другая проблема — это гигантские файлы, которые надо уметь ещё и быстро деплоить по всей инфраструктуре.


Другие причины, вроде плохой поддержки php- фишек компиляцией, можно опустить, так как они в итоге и для JIT отказались от нативного PHP в пользу Hack.

Одна из причин — необходимость двигаться намного быстрее. С PHP все-таки придется иметь дело с процессом RFC и оглядываться на потребности всего сообщества, а не только конкретной компании с конкретными задачами.

Ну да, в статье ж есть примеры, которые принципиально не работают. А, видимо, сделать систему совместимой с ними = сломать ключевые концепции архитектуры.
К примеру, достал из БД имя поля и записал в него флоат. А до этого весь код работал с ним, как с интом, и структура сишная уже инт создалась и скомпилилась. Все, рантайм эррор, приехали. Такое в мастер РНР никогда не пропустят. Видимо, из-за подобного вопрос даже не в быстрее, а просто двигаться, или не двигаться)

Ваш пример с int полем и float из базы в случае KPHP просто не скомпилируется.
youROCK Почему JIT не сможет приблизиться по скорости коду на плюсах? Там и там компилируемый код, на плюсах заранее скомпилится, с jit на лету, на следующих запросах будет использоваться скомпилированные файлы из кэша.

Интересно сейчас посмотреть сравнение kphp с php8, а не 7.4

pronskiy Так автор поста пишет что потребовалось около двух лет, чтоб вдохнуть новую жизнь в kphp и плюс еще сколько лет сделать первую версию kphp и это только процедурный код, без ООП (или я что-то пропустил). Не похоже, что этот подход быстрей RFC в PHP.
Интересно сейчас посмотреть сравнение kphp с php8, а не 7.4

Вряд ли это будет показательно. JIT в PHP в самом начале пути. На конфах разработчики прямо об этом говорят, что никаких особых оптимизаций там сейчас нет. По сути, выведение типов, чтобы проверки убрать (играет роль только для циклов), и ещё какие-то общие мелочи.
Я сравнил php8 и kphp, kphp оказался на 20% быстрее но при этом ест в 2 раза больше памяти.
Почему JIT не сможет приблизиться по скорости коду на плюсах?

Может. На синтетике может и перегнать:


Заголовок спойлера

Сырцы: https://gist.github.com/dstogov/12323ad13d3240aee8f1
Результат: https://www.youtube.com/watch?v=clMhVFllMTM&feature=youtu.be


P.S.
1) Вывод в stdout у пыха очень медленный, что явно видно на видео. У сишных сырцов только тыкаешь — оно сразу показывается. А в PHP есть задержка, которая явно заметна на видео. Результат не сразу появляется на экране. Как это затюнить — не представляю.
2) В сборке отключены все расширения (кроме опкеша) и затюнен буфер jit, перед запуском пыха явно всё прогрето.


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

Почему JIT не сможет приблизиться по скорости коду на плюсах?

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


Не похоже, что этот подход быстрей RFC в PHP.

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

может применить оптимизации недоступные JIT

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

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


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

В теории jit как раз таки должен быть быстрее AOT т.к. имеет более точные данные о выполнении программы. Про pgo я в курсе.
Потому что компилятор, имея доступ ко всему коду (или значительной его части), «понимает» чего хочет разработчик и может применить оптимизации недоступные JIT.


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

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


Делать одному дольше чем вдвоем. Если присоединились бы к команде core PHP, оптимизация и новые фичи в языке добавлялись бы гораздо быстрей.
А Так получается одно и тоже дублируется в разных форках PHP.
Весь код необходимый для выполнения запроса будет доступен JIT и его компилятор может по максимуму оптимизировать.

Если бы это было так, то компиляторы ушли бы в небытиё. Пока же код (кроме самого простого) написанный на C/C++ или даже Java/.net/Go превосходит по скорости выполнения любой JIT для большинства языков которые его поддерживают. Тот же V8, несмотря на мощный JIT, сильно уступает в производительности кода нативным компиляторам, да и редко какой JIT смотрит дальше функции которую оптимизирует (а компилятор может).


Если присоединились бы к команде core PHP, оптимизация и новые фичи в языке добавлялись бы гораздо быстрей.

Если бы убедили команду что новые фичи имеют смысл, там то ещё болото, сложнее чем патч в ядро Линуха протащить. И даже если бы убедили — ждать выхода новой версии? А дело-то стоит, пока она готовится к выходу — насколько я могу судить, VK это не совсем хобби-проект.


К тому же, будь у команды PHP хоть какой-то интерес к этому — они вполне могли и сами что-то взять — благо наработки open source, но этого не случилось.

Если бы убедили команду что новые фичи имеют смысл

Процесс RFC вроде не сложный две недели для обсуждения плюсов и минусов предложения для улучшения, две недели для голосования, никаких сложностей не вижу, это если изменяется API PHP.
К тому же, будь у команды PHP хоть какой-то интерес к этому — они вполне могли и сами что-то взять — благо наработки open source, но этого не случилось.

У них же был транслятор в C++, что команда PHP могла взять из kphp? Новую версию только открыли.
Насколько знаю JIT для PHP разрабатывается еще с версии 7.0, за это время могли предложить улучшения, чтоб получить профит в их проекте.

Что делать если предложенный RFC таки отклонили, а он важен для подающего? Или просто не имеет ценности для большинства? К тому же мало что-то предложить — предложенное и принятое нужно ещё поддерживать, а это уже несколько иной уровень.


И транспиляция в C/C++ всё же гораздо проще чем годный JIT, плюс в том что почти бесплатно получаем все оптимизации компилятора. А если транспилировать во что-то типа D (там исключительно высокая скорость компиляции и сборки) то можно вообще было на лету это делать.

Сколько наблюдаю за предложениями RFC, к каждому RFC каждый высказывал свои замечания и по этим замечаниям правили RFC и спокойно проходило голосование. Если нет можно сделать расширение к PHP.
В PHP 7.4 добавили FFI с ним можно код на C++ использовать в PHP.

Если вы делегируете кому-то право принимать такие решения, причём этот кто-то не имеет отношения к вашему проекту — вы лишаетесь контроля. В коммерческих проектах это весьма неприемлемо.

Решения принимаются сообществом PHP, принять RFC или нет.
Я сомневаюсь что у вк настолько специфичные потребности в изменениях в коде, которые будут работать только у них, и не принесут пользу сообществу, чтоб они решили отклонить RFC от вконтакте.
Если бы это было так, то компиляторы ушли бы в небытиё.

AOT-компиляторы не ушли в небытиё, не потому, что они генерируют более производительный код, а потому что в их случае нет рантаймового оверхеда, связанного с необходимостью где-то держать исходный код и/или промежуточное представление, считать профиль и т.д. А так же AOT позволяет сильно снизить время прогрева приложения. В случает, например, Java, производительность кода, порождённого AOT-компиляторами ниже, чем JIT.


Пока же код (кроме самого простого) написанный на C/C++ или даже Java/.net/Go превосходит по скорости выполнения любой JIT для большинства языков которые его поддерживают.

Это некорректное утверждение. Не бывает просто "более быстрого" кода, бывает код, который лучше ведёт себя в тех или иных задачах, и бывают случаи, когда Java уделывает C++ (а бывает и обратное). Вообще, C++ и Java просто разные языки, созданные для решения разных задач и под разное мышление программиста. Корректно сравнивать AOT и JIT компилятор для одного языка. И C++ уделывает Java только потому, что первый более низкоуровневый и позволяет вручную контролировать вещи, которые Java не позволяет (и поэтому, при грамотном подходе из C++ выжимается большая производительность)

В случает, например, Java, производительность кода, порождённого AOT-компиляторами ниже, чем JIT.

Причина этого очень проста — AOT в Java (и ряде других языков, изначально интерпретируемых) не обладает всей "мощью" оптимизаторов которые были созданы для C/C++ (и некоторых других), они были расчитаны просто на ускорение кода, а не глобальную оптимизацию, т.е. внутри это просто аналог JIT, выполняемый до запуска.


Не бывает просто "более быстрого" кода, бывает код, который лучше ведёт себя в тех или иных задачах

Давайте напишем движок для регулярных выражений на C/C++ и Java, а потом посмотрим — кто из них быстрее в итоге. Когда я говорил о "более быстром коде" — речь шла о результате компиляции. Как я уже говорил выше, JIT (и даже AOT) в Java и других подобных языках работает в пределах одной функции (не уверен даже что инлайн умеет) и лишен ряда оптимизаций, тут вы ничего сделаете (пока не напишите хотя бы компилятор Java в LLVM с последующей прогонкой оптимизатором).


бывают случаи, когда Java уделывает C++ (а бывает и обратное)

Можете привести хотя бы один такой случай как пример? Только при условии что код не использует ничего кроме стандартных возможностей языка, т.е. CPU-bound.


Я ещё ни в реальной жизни, ни в бенчмарках не видел чтобы Java/.net побили C/C++ (при адекватной реализации, разумеется, ляпы не в счёт).


C++ уделывает Java только потому, что первый более низкоуровневый

Это одна из причин, не самая главная (и имеет смысл только если человек пишет код с учётом этого, а не "в лоб"). Самая главная всё же наличие очень оптимизирующих компиляторов. Если мы возьмём сложный (и много) CPU-bound код, напишем его одинаково (минус синтаксис) на C++ и Java то Java проиграет GCC/LLVM при любом раскладе — с AOT или JIT.

не обладает всей "мощью" оптимизаторов которые были созданы для C/C++

Боюсь, у меня тут недостаточно экспертизы, т.к. я не копался во внутренностях оптимизаторов C++, но исходя из моей практики написания AOT-компилятора для Java, который специально делался с глобальными оптимизациями и исходя из информации, прочитанной мной из статей на эту тему, время, необходимое более-менее умным алгоритмам чтобы оптимизировать хорошо, устремляется в бесконечность. Поэтому за счёт чего может выиграть AOT-компилятор — у него время самой компиляции не ограничено, поэтому можно применить просто чуть более мощные алгоритмы, дающие чуть лучшую производительность в некоторых ситуациях (например, graph-coloring register allocator вместо linear scan register allocator).


JIT (и даже AOT) в Java и других подобных языках работает в пределах одной функции

JIT и AOT-компиляторы в Java очень хорошо инлайнят. Проблема только в том, что чтобы заинлайнить вызов, он должен быть мономорфным (ну или биморфным, если конкретный компилятор умеет). А алгоритмы, которые могут хорошо доказать мономорфность вызова, ну очень требовательны к ресурсам и нигде не применяются, насколько мне известно. Поэтому применяются более практичные и топорные алгоритмы, которые, увы, дают весьма консервативную оценку. Это я говорю как человек, написавший сравнительно неплохой девиртуализатор для Java. Так вот, у JIT с этим проблем нет вообще, т.к. они смотрят, какие классы БЫЛИ на callsite-е в реальности во время прогонов интерпретатора (с деоптимизацией, если предположение оказалось неверным и повторной оптимизацией под новые реалии).


Можете привести хотя бы один такой случай как пример? Только при условии что код не использует ничего кроме стандартных возможностей языка, т.е. CPU-bound.

Нет, не могу. У меня были примеры в моей практике, но код, увы, закрыт. А лезть в интернет и искать бенчмарки я не хочу. Так вот, в моей практике было, что числодробильный код, написанный на Java и на C++ работал с одинаковой производительностью, если его скомпилировать gcc. И C++ проигрывал Java при компиляции clang и msvc. Код на C++ писали люди, которые хорошо владеют C++ (а не просто джависты, которые дорвались до C++).

И C++ проигрывал Java при компиляции clang и msvc

Иногда оптимизатор ошибается и результат медленнее чем могло бы быть, или просто не учитывалась архитектура процессора для которого генерился код — это единственное логичное объяснение.


Код который сравним по времени выполнения — ок, ничего удивительного, но вот Java быстрее — это скорее аномалия, вряд-ли могущая проявить себя "в среднем".


Но если вернуться к PHP… боюсь, его JIT ещё предстоит очень долгий путь к тому что достигнуто в Java, так что транскомпиляция в C++ кажется всё же более оптимальным вариантом если нужно здесь и сейчас.

Вот интересно стало: если взять современную Java и какой-нибудь C++ самых первых версий…

На хабра не раз были языковые войны, я там точно в статьях и комментах видел пруфы, что жава и с++ код вполне себе одинаковую скорость исполнения имеют, но, наверное, не на всех задачах
Потому что компилятор, имея доступ ко всему коду (или значительной его части), "понимает" чего хочет разработчик и может применить оптимизации недоступные JIT.

По идее, opcache.preload должен решить эту проблему JIT-а.

Зато в динамическом коде где вывести тип kphp не удалось, в теории JIT может дать более шустрые конструкции чем статическая компиляция.

Как минимум — накладные расходы на zval, как по объёму занимаемой памяти, так и по скорости доступа к конкретному значению

1) Ригдное комьюнити и процесс апрува изменений.
2) Велосипеды точатся под свои задачи, опенсорс — под general case. Некоторые вещи в таких случаях не должны попадать в общее пользование по различным причинам — плохая семантика, специфичный функционал и тп.
3) Писать JIT дело не простое и допускаю, что не решает проблем которые необходимо решить у них в ВК.

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

На фронтенде у ВК при Дурове был голый JS с множеством самописных костылей, а сейчас вот новые модули стали и на реакте делать.
На мой взгляд, аргумент это довольно слабый: в конце концов, никто не мешает разбивать код на микросервисы, связанные RPC

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


Ждем, пока этот монолит коллапсирует в сбербанкчерную дыру

Можно изобретать велосипеды, а можно платить в разы больше денег за сервера просто так. KPHP — это серьезная экономия денег.
Можно изобретать велосипеды, а можно платить в разы больше денег за сервера просто так. KPHP — это серьезная экономия денег.

Можно просто писать на условном go, серьёзно экономя время и деньги.


KPHP — это серьезная экономия денег.

Путем разработки целого транслятора-компилятора?


Путем создания целого нового языка, которому нужно еще и обучать?


Путем разворачивания огромных distcc-ферм для компиляции этого монолита?


Какой у вас там CI/CD медленный и кошмарный я боюсь представить.


Короче, трешак уровня The Inner JSON Effect.

Путем создания целого нового языка, которому нужно еще и обучать?

Вроде KPHP — это подмножество PHP. По сути ничем для новичка не отличается от "у нас такой код стайл — нельзя в массивах смешивать разные типы, нельзя обращаться к методам/свойствам/переменным по динамическому имени и т. п. (такие ограничения могут быть и без KPHP) и всё проверяется линтером, который называется KPHP" )

Сколько вам понадобится времени, чтобы переписать, допустим, 6-7 миллионов строк продуктовой логики с PHP на тот же Go? Причем этот код постоянно меняется десятками разработчиков, а останавливать проект никто на год-другой не даст.

Тут вариантов остается два: выносить части в отдельные сервисы на произвольном ЯП (и такие работы у нас ведутся, но это оооочень долгий процесс для такой кодовой базы), и замена рантайма используемого ЯП.

Силы небольшой команды, занимающейся KPHP, экономят просто море ресурсов компании, и позволяют идти обоими вышеприведеными путями.

Путем создания целого нового языка, которому нужно еще и обучать?

Говорилось же, что язык максимально похож на обычный PHP уровня 7.3 — 7.4. Разработка вообще сидит на локальных апачах для тестирования нового кода.

Какой у вас там CI/CD медленный и кошмарный я боюсь представить.

Ну да, сборка и деплой на все тысячи серверов может занимать минут 20. Плохо?

Сколько вам понадобится времени, чтобы переписать, допустим, 6-7 миллионов строк продуктовой логики с PHP на тот же Go?

KPHP переписывает его на C++

Да, но результат нельзя взять как основу для дальнейшей разработки проекта на плюсах.
Даже интересно, что будет, если всем PHP-разработчикам завтра сказать: отныне вы пишите на плюсах, вот новая репа с одним initial commit, а да, только не на 6 миллионов строк, а на 66, там 250к файлов, а все строковые литералы объединены в оооодну большую строку :)

Вы не могли бы провести анализ этих особенностей сгенерированного кода и сказать, насколько они продиктованы принципиальными ограничениями задачи, а насколько тем, что не ставилась задача сделать модифицируемый C++?

Можно на каком-нибудь мелком примере.
Например, безобидный PHP-шный foreach:
foreach (getArr() as $k => $v) { ... }


В C++ нужно: объявить переменные $k, $v; объявить временную переменную, куда присвоится вызов функции getArr(); сделать цикл через for по итератору, внутри этого цикла присвоив в $k и $v ключ и значение из этого итератора; не забыть, что в общем случае если вместо getArr() какая-то локальная переменная, то этот массив может меняться внутри тела цикла (в PHP это норм практика), поэтому с итераторами там тоже не всё банально; не забыть уменьшить рефкаунтер после цикла, т.к. туда дополнительно ссылается временная переменная.

В итоге этот foreach превращается в весьма громоздкую конструкцию, и это нормально, потому что нам нужно покрыть все возможности PHP массивов.

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

Еще он не является GO.


Вопрос насколько можно преобразовать Restricted PHP в читаемый/модифицирцемый Go.

Ну да, сборка и деплой на все тысячи серверов может занимать минут 20. Плохо?

20 минут на тостере и 20 минут на кластере — абсолютно разные вещи (и деньги).


Разработка вообще сидит на локальных апачах для тестирования нового кода.

Мягко говоря, странно, что против продакшон-билда даже тесты не запустить, и разработки ведутся под значительно отличающиеся среды.


Говорилось же, что язык максимально похож на обычный PHP уровня 7.3 — 7.4.

Это прямо сейчас, а судя по статье, на протяжении многих лет это было не так.


Сколько вам понадобится времени, чтобы переписать, допустим, 6-7 миллионов строк продуктовой логики с PHP на тот же Go?

Монолит на 6-7 миллионов строк никому не даст переписать здравый рассудок (если, конечно, оно не состоит на 99% из HTML). Но суть не в том, а в том, что монолит — показательный продукт той самой культуры, о которой я говорю. Проблемы должны были быть очевидны уже на первом миллионе.

20 минут на тостере и 20 минут на кластере — абсолютно разные вещи (и деньги).

Во первых, речь про весь пайплайн коммита от машины разработчика до работающего сервера в проде, а не только сборка. Обычно, конечно, код выезжает по расписанию, а не вот так вот «побыстрее».

Во вторых, самое медленное тут звено — компилятор C++ (даже в инкрементальном режиме), а далеко не kphp2cpp. Так что это время и железо, на котором gcc будет компилировать N миллионов строк кода. Можно попробовать собрать какие-нибудь проекты типа Chromium на тостере.

Мягко говоря, странно, что против продакшон-билда даже тесты не запустить, и разработки ведутся под значительно отличающиеся среды

Это можно воспринимать как преимущество качества реализации всехз особенностей php внутри kphp. Все настолько хорошо поддержано (либо оперативно правятся найденные corner case), что разработка на обычном php вполне подходит.
А вот руками, или обязательно при пуше, уже гоняются всевозможные тесты.
Так мы получаем и возможность быстрой разработки на php (и минусы языка, конечно), и плюсы kphp в итоге.

Это прямо сейчас, а судя по статье, на протяжении многих лет это было не так.

Про последние годы и речь. Смысл обсуждать что-то старое?

Но суть не в том, а в том, что монолит — показательный продукт той самой культуры, о которой я говорю

Той, что позволила ВК максимально быстро развиваться?
Это очень старая и распространенная дилема: можно или все делать по уму (и с большой вероятностью загнуться до популярности), или быть растущим проектом, который часть ресурсов тратит на техдолг.
Говорилось же, что язык максимально похож на обычный PHP уровня 7.3 — 7.4.

Язык — это не только синтаксические возможности, но и библиотеки, и комьюнити.

Т.е., да, можно говорить, что KPHP практически не отличается от оригинального языка, но весь опыт его применения будет за скобками PHP. И это тоже косты для компании, что весь функционал обязан опираться исключительно на «invented here» библиотеки.

А вы думаете, работа в Гугле или ФБ сильно чем-то отличается в этом плане? :)

что весь функционал обязан опираться исключительно на «invented here» библиотеки


Это больше к используемым нами БД, а не к (K)PHP.
Решения на Go и C/C++ тоже используют в основном «invented here библиотеки», потому что они очень заточены под эффективное решение именно наших задач.
В PHP универсальный контейнер внедрения зависимостей легко и удобно реализуется через рефлексию. Но если вы говорите, что в KPHP рефлексии нет, то хотелось бы посмотреть пример реализации этого контейнера в рамках возможностей языка.

У них есть AST в компайл-тайме.

Каким образом compile-time AST можно использовать в DI? Приведёте пример кода?

Для определения типов параметров в конструкторах, методах, типов переменных и подстановки в них нужных реализаций при запросе сервиса у контейнера. По сути контейнер будет хардкодом типа


if serviceName = RequestInterface return new Request::fromGlobals;
if serviceName = UserRepository return new ORMUserRepository;
if serviceName = UserController return new UserCOntroller(new Request::fromGlobals, new ORMUserRepository)

new UserCOntroller(new Request::fromGlobals, new ORMUserRepository) — это не контейнер DI.
Должно быть нечто подобное:
new UserCOntroller($this->instance(RequestInterface), $this->instance(UserRepository))

Но в таком подходе мы должны вручную продублировать все возможные зависимости между классами. ИМХО, это будет даже хуже, чем «ручное» конструирование каждого объекта.

Это код внутри контейнера, тело метода $this->instance(). Автогенерированный на основе AST код. Типа как в Symfony контейнер для прода компилируется до запуска приложения. А вызовы $this->instance(UserRepository) заинлайнены.

Если контейнер в точке своего создания знает все классы, которые он включает, такое может сработать.

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

И глобальная кодогенерация тоже не сработает: контейнер в коде не один и в одном контейнере в класс A, требующий интерфейс Q, инъектируется класс B, но, одновременно, в другом контейнере в тот же A инъектируется класс C…
Интересно бы посмотреть на производительность в сравнении со Swoole / Workerman.

Запилите тесты для Techempower Benchmark?
Не очень корректно сравнивать со Swoole. У одних — асинхронный MySQL, у других — «движки». А без запросов к тяжелым внешним I/O, на числодробилке, победит KPHP. Брать чтото общее, что есть у VK и есть подход у Swoole (условный кликхаус) — не получится, «движки» они не публикуют.

Вообще, отсутствие сравнимого источника данных (движка) — как раз и не даст запилить чтото для Techempower. Разве что свою базу написать, на «голом» KPHP. Но опять таки, в некоторых кейсах использование внутри-swoole-вского массива будет быстрее чем запросы к MySQL из Swoole, а это тоже некорректно для сравнения.
Кстати, а сколько нужно оперативы для линковки этого ./vk? Машин разработчиков вообще хватает, или только в CI?
У нас всё-таки чересчур много кода, и нестрипанный бинарь получается почти 3 ГБ, который линкуется из более чем 100к объектников (не втупую, там свои приколы). Поэтому линковать его на локальной машине это так себе затея) Но унести бинарник vkcom на флешке домой это можно, получается.
Но унести бинарник vkcom на флешке домой это можно, получается.
А много было прецедентов?
есть какие то подводные камни когда бинарник такой толстый? может есть статейка на эту тему?

Спасибо за статью и за то, что открыли исходники!


Однако, как у человека, который работал в ВК не так давно, хотел бы уточнить один момент:


Если говорить про бенчмарки, то на средних VK-страничках у нас профит от 3 до 10 раз. А на конкретных участках, где мы прицельно выжимали максимум, — до 20–50 раз.

Расскажите пожалуйста, как Вы тестировали, и на каких страницах есть выигрыш, и почему. Когда я пару лет назад тестировал производительность сайта под PHP 7.2, для более-менее честного сравнения отключался xdebug и development режим сайта, поскольку оба дают очень существенный оверхед при исполнении. В таком режиме многие страницы, где не используются асинхронные запросы (в PHP коде вместо этого ведь просто заглушки стоят), выполнялись со сравнимой скоростью (страницы вроде списка друзей или мессенджера отрабатывали за такое же время, как и KPHP, плюс-минус 10%). Некоторые страницы, вроде ленты, действительно сильно заточены под KPHP и работали в ~10 раз медленней, но в общем и целом разница была не такая большая, и точно не в 3-10 раз. Причём во большинстве случаев разница была из-за того, что в PHP не реализован тот вид асинхронных запросов, который есть в KPHP, но само ядро PHP вполне поддерживает те же концепции, поскольку как минимум есть конструкция yield, которая точно также сохраняет состояние функции в произвольном месте и умеет восстанавливать его обратно.


При этом, конечно же, на коде, который использует полностью типизированные классы и структуры вряд ли что-то может быть сильно быстрее KPHP, потому что он буквально транслирует этот код в C++ почти что один-в-один, и, как мне кажется, это и является единственным существенным преимуществом KPHP перед современными версиями PHP, и, вероятно, даже с появлением JIT в PHP8 всё равно производительность KPHP будет выше, если специально затачивать код под него.


Просто хотелось поменьше голословных утверждений про производительность KPHP на реальной кодовой базе и больше деталей и примеров по поводу того, какой код действительно ускоряется с помощью KPHP, а какой — нет, или даже работает медленней современного PHP, который тоже на месте всё это время не стоял.

Юрий, по-моему, ты сам ответил на свой вопрос :) Ты ушёл из ВК как раз чуть меньше 2-х лет назад, когда наша разработка входила в активную стадию. На тот момент у нас были просто структуры (без ООП), и мы только начинали свой путь. Но кстати даже тогда, когда повсюду были ассоциативные нетипизированные массивы — даже тогда KPHP выигрывал больше, чем 10%, тут ты занижаешь. Хотя не в 3-10 раз, как сейчас, тут конечно.


И с тех пор как раз мы взяли курс на тотальную типизацию. Полная поддержка ООП, напрямую идущая в плюсы. Типизировали RPC-слой с движками, что TL-байты напрямую маппятся в PHP-типы в обе стороны. Обязали писать типы везде: даже если у тебя legacy и везде mixed — иди и пиши явно. Плюс ряд оптимизаций, не связанных с типизацией — чего стоит одна шаренная память между воркерами с иммутабельным доступом. По факту, почти всё что мы сделали — это как раз после твоего ухода )) Так что да, теперь KPHP значительно быстрее — и как ты правильно сказал, в основном за счёт типизации и за счёт фич, которых в PHP нет. А если его использовать абы как, то PHP кое-где случайно и может окажется быстрее. Но это не наш случай.

Но кстати даже тогда, когда повсюду были ассоциативные нетипизированные массивы — даже тогда KPHP выигрывал больше, чем 10%, тут ты занижаешь.

Ну времена работы многих страниц (повторюсь, в основном, конечно же, тех, где нет или почти нет асинхронного кода) правда мало отличались. Так и должно быть, потому что основной выигрыш в производительности от PHP7 по сравнению с PHP5 как раз и был в том, что были оптимизированы внутренние хэш-таблицы, а JIT, как оказалось, на реальном PHP-коде давал не так уж и много.


Хотелось бы всё-таки увидеть полноценную методологию тестирования с цифрами (хотя бы относительными, чтобы не нарушать NDA и прочее) и анализом CPU usage и прочего, чтобы сравнивать именно производительность PHP без учета асинхронного кода против производительности KPHP без учета асинхронного кода. Также нужно сделать сравнение TL-схемы честным, чтобы и для PHP и для KPHP использовались одинаковые механизмы (поскольку для PHP тоже можно десериализовать TL-схему в расширении и генерировать готовые классы сразу из расширения, и это будет на порядок быстрее десериализации на самом PHP), отключить xdebug и использовать production-режим, где не считаются стректрейсы для отладки на каждый вызов RPC. И также не резолвятся имена хостов без нужного кеширования (т.е. вместо localhost используется 127.0.0.1, например).


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


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

Расскажите про это подробнее как-нибудь, пожалуйста :).


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

Совершенно не случайно. Ядро обычного PHP тоже оптимизировано очень хорошо для того кода, который обычно встречается на практике (то есть этот код не содержит строгих аннотаций типов, например). Плюс в opcache в PHP точно также кешируются константные значения, даже для массивов, и в целом оверхед от рантайма обычного PHP меньше, например в плане потребления памяти, чем в KPHP. Ну и в целом обычный PHP тестируется на реальных кодовых базах за пределами VK, так что несложно представить себе ситуацию, что в том же opcache или в SSA представлении будут существовать оптимизации, которых нет в KPHP, но для конструкций, которые часто используются в сторонних (по отношению к ВК) кодовых базах на PHP.


Но это не наш случай.

Я бы не был так категоричен. Код ВК тоже является в первую очередь кодом на PHP, и во вторую это уже некоторое подмножество, которое хорошо работает с KPHP. Тем не менее, я рад, что вы выложили свои наработки в open source и надеюсь, что поддержка ООП и прочего в KPHP уже достаточно хороша для того, чтобы можно было запустить какие-нибудь реальные проекты на его основе без слишком больших модификаций. Надеюсь увидеть от вас больше статей, но в которых поменьше хвастовства и побольше «мяса» и технических деталей.

Мы рассчитываем, что в дальнейшем нашей команде — возможно, при помощи сообщества — удастся развить KPHP так, чтобы он стал полезным инструментом и вне ВКонтакте. Не так важно, как быстро это произойдёт. В любом случае, это тот ориентир, который теперь стоит перед проектом.

Честно говоря, не очень понятно, зачем эта цель (и вам, и сообществу). В конкретном случае (очень много легаси-кода на PHP) — да, ок, вероятно это имеющее право на жизнь решение. Но мне сложно представить ситуацию, в которой у кого-то ещё снова может возникнуть подобная необходимость. Это нужно ведь, чтобы кто-то решил начать новый проект на PHP (а не на Go, скажем, да и даже не на PHP 8 почему-то), вырос до тех размеров, когда уже нет желания переписать на какой-то другой язык — но при этом есть желание переписать код так, чтобы он успешно компилировался kPHP…

Кажется, вы зря возлагаете надежды на сообщество. Пусть вы и оформили kPHP покрасивше, чем в 2014, но пользы для кого-то, кроме самого ВК, от него немного. А если уж кто-то и горит желанием развивать нечто компилирующееся в C++, я бы предложил лучше потратить силы на Nim, например, — у него, по крайней мере, нет цели одновременно подражать другому языку (который сам по себе так себе образец для подражания), и при этом отбирать из него целые пласты функциональности :)

Побуду немного адвокатом дьявола. В VK разработка идет на обычном PHP, а KPHP используется только для финальной сборки кода на продакшене, поэтому разработческий опыт при разработке с использованием KPHP и при использовании обычного PHP отличается слабо. При этом, PHP до сих пор очень хорошо подходит для разработки в вебе, в том числе и для новых проектов, даже по сравнению с языками с быстрой компиляцией, такими как Go. В PHP действительно работает парадигма «сохранил файл, перезагрузил страницу, посмотрел, что изменилось», и это очень сильно помогает при разработке, особенно в начале.


Даже если у вас есть большой готовый проект, который мало использует рефлексию и прочее (хотя бы из соображений производительности) и код всё равно из себя в основном представляет из себя ООП с уже прописанными аннотациями типов, KPHP может дать очень большой выигрыш в производительности за счёт того, что он компилируется в почти что эквивалентный C++. Стоит ли того переделка кодовой базы (или допиливание фич в KPHP) или нет, решается на основе того, сколько стоят альтернативы: переписать существующую и хорошо отлаженную, пусть и legacy, кодовую базу с нуля на Go будет намного дороже и рискованней для бизнеса, чем адаптация существующего кода под новые реалии. Если производительность PHP-кода действительно становится узким местом и у вас много серверов, то, как мне кажется, вариант с KPHP может и взлететь, даже если для этого нужно будет добавить в KPHP какие-то недостающие для вас фичи.

Есть проблема в том, что подавляющее, наверное, большинство проектов или базируются на зависимости, активно использующих концептуально не поддерживаемые в KPHP возможности PHP (WordPress, Laravel самые популярные, наверное) или сами активно ими пользуются. Я уж молчу про отсутствие расширений типа mysql.

В VK разработка идет на обычном PHP

А как тогда они на обычном PHP тестируют методы, возвращающие tuple() и другие KPHP-шные штуки?
А как тогда они на обычном PHP тестируют методы, возвращающие tuple() и другие KPHP-шные штуки?

Ну заглушку можно сделать, которая делает всё тоже самое.


function tuple(...$args): array
{
    return $args;
}
Да, всё правильно описал SerafimArts выше. Реализация tuple() чуть страннее выглядит в реальности, конечно, но принцип такой. У нас это называется «полифиллы» — github.com/VKCOM/kphp-polyfills
UFO just landed and posted this here

Да, всё так. Для распространения своего же кода, для распила монолита, это удобно и стыкуется с привычной разработкой.

А почему "был"? Я им никогда не пользовался, но вроде как проект жив, и даже новую версию в сентябре анонсировали.

Да, вы правы, вижу он действительно релизится. Хотя почему-то был уверен, что в этом году видел новость про закрытие проекта
Новость была не про закрытие проекта, а про отказ от развития Phalcon как скомпилированного подключаемого модуля. Предполагалось, что новая версия Phalcon будет написана на PHP и иметь производительность на уровне других PHP-фреймворков.
habr.com/ru/post/518064

Да, не знал. Тут я с вами соглашусь. Интересно, как долго Фалькон просуществует в новой ипостаси.

UFO just landed and posted this here
Он жив конечно же, но уже со времен php 7.4 его преимущество по скорости стало не таким явным. Кроме развития самого php, другие фреймворки тоже не стояли на месте все это время. Появилось много легковесных фреймворков, а такие монстры как Symfony заметно «похудели» и ускорились за прошедшие годы. И вот сейчас, в конце 2020-го года я не смогу придумать ни одной веской причины начинать разработку нового проекта на именно фальконе, хотя когда-то сделал на нем достаточное количество проектов и активно «топил» за переход на него с монструозных Zend или Symfony.
Symfony в некоторых местах провели аналитическую работу и сделали «чудо», алгоритмически, алгоритмами ускорив работу. Например, роутер на компилируемой регулярке — если написать обычный роутер (foreach(routes){ if(route.regexp ~= URL) }) хоть на си, хоть на ассемблере, он будет дольше работать, чем на старом добром PHP, потому что алгоритмическая сложность меньше (за счёт потраченного времени CPU на компиляцию этой регулярки).
В 2014 году в техническую команду пришли новые люди, которые начали заниматься движками. (Да, ВКонтакте до сих пор десятки собственных закрытых движков, хотя точечно мы используем ClickHouse и другие известные.) Но KPHP долго никто не трогал. До 2018-го бэкенд-код действительно был на уровне PHP 4.5, а IDE плохо понимала код и почти не подсказывала при рефакторинге.

Интересно было бы узнать, каковы шансы, что KPHP опять не уйдет в тьму на 6 лет? Есть какая-то дорожная карта?


И второй вопрос — насколько сложно лучшие достижения KPHP перенести в основной PHP? И есть ли в этом вообще смысл?

> каковы шансы, что KPHP опять не уйдет в тьму на 6 лет
По крайней мере, если в 2014 выложили и всё, то сейчас у нас весь процесс разработки переехал на гитхаб. Да, не факт, что у нас будет много времени на то, чтобы делать что-то для не нужд ВК (и в ближайшее время точно не будет) — но весь процесс разработки в любом случае становится открытым. Так что ответ зависит от трактовки слова «тьма» :)

> лучшие достижения KPHP перенести в основной PHP
Думаю, что шансов примерно 0. Во-первых, мы совершенно сторонняя компания, не имеющая никакого отношения к Zend. Ну и во-вторых, мы ведь живём за счёт ограничений и за счёт анализа всех исходников целиком, а не по мере исполнения.
Во-первых, мы совершенно сторонняя компания, не имеющая никакого отношения к Zend.

Как и JetBrains, Badoo, Facebook и другие компании, которые очень много сделали для языка.


Ну и во-вторых, мы ведь живём за счёт ограничений и за счёт анализа всех исходников целиком, а не по мере исполнения.

PHP 7.4 прелоадинг живёт тоже за счёт анализа исходников перед их исполнением. Понимаю, что это далеко не аналог шага компиляции, но сам механизм "сборки перед исполнением" есть.

PHP 7.4 прелоадинг живёт тоже за счёт анализа исходников перед их исполнением.

Прелоадинг решает вполне конкретную проблему пустого opcache при старте. При этом имеет существенные недостатки, ограничивающие его применение.
Это ускоряет компиляцию (для умираемого PHP это жирнющий кусок), но не ускоряет рантайм. KPHP считерил, оставив строгую типизацию на уровне С++, и чем больше код похож на тупую числодробилку (рекомендации, умножение матриц, умножение векторов в CBOW и word2vec, другие необычные штуки), тем быстрее он будет. Ускорить такое дело можно только через CUDA и шейдеры.

То есть вроде в прелоадинге PHP как собрали код в «нечто», но это нечто из байткода ещё нужно пропустить через процессор и оперативную память, туда-сюда шерудя преобразованиями типов, хеш-таблицами и так далее, вместо прямого обращения к памяти через указатели и оффсеты числовых массивов. Потому что строго говоря, в Go и C++ a[23] прекрасно компилируется в несколько тактов процессора, которые получают указатель на конкретный кусок в памяти (мы знаем про смещение + 23*размерблока), а в PHP будем искать хеш от «23» (да, я знаю про числовые индексы в новом PHP и их оптимизацию, тут я утрирую конечно) или делать проверки вида «а не преобразовать ли нам тип прямо сейчас?».
Но вот проблема: KPHP-то понимает, а вот IDE нет.

И IDE тоже понимает


/** @return array{0: int, 1: User} */
function getTotalAndFirst(): array {}

Нет, про psalm, который нынче уже из коробки идёт.

Почему бы не использовать LLVM? PHP -> LLVM IR -> .o + gold -> ваш бинарник.
транслировать в высокоуровневый язык сильно проще, чем в LLVM

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

Будет лучше хотя бы в том, что вы сможете уйти от C++ вообще и g++ в частности. Получите более гибкую настройку оптимизатора + легко сможете добавить свои оптимизации. Или например, зачем вам плюсовый ABI, легко сможете от него отступать или сделать вообще свой.
Я подразумеваю, что первый раз бэкенд VK (а ведь это не только kphp, а ещё и бд, и движки для многих типов сущностей) был выложен для того, чтобы на нём крутить бэкенд Telegram юридически легальным способом.

Зачем же выкладывать обновления повторно?
Пусть в качестве ответа на «Зачем?» будет «Но ведь хуже-то от этого не станет».
Открытость для нас как для бренда компании — это весьма достойно, хоть и многими воспринимается с изрядной долей скепсиса. Открытость для нас как для разработчиков — это как минимум личная ценность, что ты не просто «где-то там работал», а результаты твоих трудов доступны и лежат в открытом доступе. Тем более, что компиляторная область в целом весьма узкая.
И раз мы переезжаем на гитхаб — то конечно, куда без статьи на Хабре :) Ничего сверхестественного.
И это здорово!
Я как раз искал язык программирования для веба под лицензией GPLv3
А что общего между бекендом Telegram и VK, кроме Дурова?
В итоге всё линкуется в один огромный бинарник (это весь vk.com)

И сколько этот огромный бинарник весит, если не секрет?

Расскажите, что выглядит более интересным и перспективным — подмножество php с транспиляцией в С++ или Rust? Только честно, без sunk cost fallacy.

Честно — не знаю. Возможно, в LLVM :)
Но поскольку мы уже несколько лет как завязаны на С++ и бесконечность с этим связанных мелочей, то «давайте полноценно сравним с Rust» звучит как «давайте сменим PHP на Go».

А вы не рассматривали возможность транслировать не в C++ а во что-то другое?
С прицелом на последующее выкидывание PHP и своего плагина и использованием IDE которые фуллтайм команды пишут для языка со статической типизацией?


И еще — на каком этапе валидируется возможность трансляции PHP, который написал программист, в C++? IDE? Кастомный валидатор? Тесты?

Первая часть звучит как синоним «просто откажитесь от PHP», что в разных ветках уже обсуждалось.

Возможность трансляции — да по факту запуск компилятора :) Сработало — всё ок, вывел ошибку — идёшь исправляешь. Да, частично это видно в IDE при плагине, но далеко не всё.

В ответ прозвучало "Как бы слабо ни звучал аргумент «у нас миллионы строк кода» "


Но эти миллионы строк уже переписываются на C++ много раз в день автоматически.


Возникает вопрос, почему не сделать это один раз и выкинуть PHP, например?

Потому что PHP это действительно очень удобно для быстрого прототипирования, что очень актуально для продуктовых команд. Исправил, сохранил — и уже работает. 0 степеней ожидания.

Я к тому, что в Rust есть очень много всего вкусного, чего точно нет в обрезанном php. Более того, rust с собой принесёт очень много строгости и тщательности, когда нельзя просто "сделать вид, что проблемы не существует".

UFO just landed and posted this here

«Невозможно» — сильное слово, однако чтобы корректно выводить красивый (symbolized, demangled, с учётом инлайнинга, etc.) стектрейс в обработчике сигнала, требуется простыня впечатляющих размеров (вот, например, реализация только содержательной части пункта про «красивый» из Abseil). А для получения стектрейса как набора адресов (возможно, даже с чем-то похожим на имена символов и смещения относительно них) достаточно и glibc (с некоторыми оговорками про AS-safety).

Интересно поиграться, но вот самое тяжёлое у нас на проекте сейчас ORM — а это всегда (?) рефлексия или динамический биндинг кложуры. Ладно с расширениями, кто-то может и напишет, а вот библиотеки…

биндинг кложуры на геттеры ORM полей?..

На сами поля. Это самый эффективный способ гидрации.

Биндинг на объект для доступа к его приватным полям. Хоть для чтения, хоть для записи.

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

Это же отпугивает сотрудников VK от покидания компании — их опыт никому не нужен. Меньшая текучка.

"Отличный" пример имплементации Job-lock'а

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

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

К нам приходят люди с очень разным опытом; а задачи, которые они будут решать, так же зависят от опыта. Далеко не все в компании пишут на PHP, есть же еще как-минимум C/C++ и Go.

Так что «выходец из ВК» — это скорее человек, который умеет решать сложные и нетривиальные по нагрузкам и шардированию задачи, а не используемый при этом ЯП.
Понятно, что в случае решения задач основного web'а проекта, это задачи в основном на (K)PHP.

Так что проблема тут скорее — это жесткая привязка к нашим внутренним БД, а не ЯП.
Мы никогда не поддерживали стандартные базы, потому что это не было нужно.

Где тогда хранится информация о пользователях, сообществах, постах...?
UFO just landed and posted this here
Пусть лучше сотни ваших разработчиков пофиксят багу с поиском друзей по фильтру, которой уже больше года актуальна.
этой соцсетью пользуются те, кого не успели посадить в тюрьму, когда админы вконтакта сливали личные данные пользователей органам даже безо всяких судебных постановлений?
unserialize
Подскажите, где можно получить помощь или совет по компиляции php->c++ хотя бы hello world?

На свежеустановленную ubuntu 20.04.1 по инструкции добавил репозитарий и установил kphp, при любой попытке запуска (кроме вывод хелпа), даже просто kphp -v 3 - выдает:
Заголовок спойлера
Fatal error [gen by ../compiler/compiler-settings.cpp at 293]
In stage = []:
[file = unknown]
[function = unknown function:-1]
Assertion dir_pos != std::string::npos failed

Compilation failed.
It is probably happened due to incorrect or unsupported PHP input.
But it is still bug in compiler.
[pid 77732] [time 1605344882] SIGABRT caught, terminating program
[pid 77732] [time 1605344882] errno = No such file or directory
[pid 77732] [time 1605344882]
------- Register Values -------
[pid 77732] [time 1605344882] RIP=0x00007F7D4F5CE18B RSP=0x00007FFCAD0EC0F0 RBP=0x00007FFCAD0EC400 RDI=0x0000000000000002 RSI=0x00007FFCAD0EC0F0 RDX=0x0000000000000000 RCX=0x00007F7D4F5CE18B R8=0x0000000000000000 R9=0x00007FFCAD0EC0F0 R10=0x0000000000000008 RBX=0x00007F7D4FAFD780 RAX=0x0000000000000000 CR2=0x0000000000000000 R11=0x0000000000000246 R12=0x00007F7D4F7746A0 R13=0x0000000000961438 R14=0x00007FFCAD0EC3A0 R15=0x00007FFCAD0EC370
[pid 77732] [time 1605344882]
------- Stack Backtrace -------
kphp[0x73c16d]
kphp[0x73c996]
/lib/x86_64-linux-gnu/libpthread.so.0(+0x153c0)[0x7f7d4faed3c0]
/lib/x86_64-linux-gnu/libc.so.6(gsignal+0xcb)[0x7f7d4f5ce18b]
/lib/x86_64-linux-gnu/libc.so.6(abort+0x12b)[0x7f7d4f5ad859]
kphp[0x4d9877]
kphp(_ZN16CompilerSettings4initEv+0x2075)[0x6b7f35]
kphp(main+0x213c)[0x4e8a3c]
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf3)[0x7f7d4f5af0b3]
kphp(_start+0x2e)[0x4ea56e]
[pid 77732] [time 1605344882] -------------------------------
[pid 77732] [time 1605344882] kphp2cpp compiled at Nov 11 2020 07:52:08 UTC by gcc 9.3.0 64-bit after commit 1cb480048d1b2102b60e50c04e58e601b0d37765 build 2195[pid 77732] [time 1605344882]


в докере происходит та же фигня
Похоже, что ты не передаёшь имя главного файла или он не существует. Типа, вызываешь просто `kphp`, а не `kphp some_file.php`.
Оказывается, тогда мы падаем некрасиво — сами не натыкались, т.к. у нас во внутренних скриптах всегда имена корректные )) Но вот уже поправили, чтоб писал нормальную ошибку — https://github.com/VKCOM/kphp/pull/5, видимо ровно оно :)
Я указывал — думал возьмет файл из stdin

Сейчас вроде работает.

Первоначально я начинал пробовать на ubuntu в wsl там такая ошибка появлялась и при указании существующего файла (полагаю тут вылезали проблемы самого wsl) установил в новой системе но не проверил работу с файлом

О, помню эту штуку еще когда она KittenPHP называлась

Sign up to leave a comment.