Pull to refresh

Comments 38

Замечательная тема.
Вы дойдёте до структуры байт кода и создания своего бинарного компилятора?
Нет, оставим это на совести g++.
Я имел в виду не машинный байткод, а для типа того, что генерирует zend encoder. Чтобы потом этот же модуль его мог преобразовать в обычные структуры zend_op и выполнить цепочку.
Загляните в исходный код всевозможных PHP акселераторов/байт-код кэшеров, там всё есть.
Знаю. Но расписать эту тему на хабре было бы очень интересно для разработчиков, я считаю.
До таких глубин я еще не добрался. Но мало ли, чем черт не шутит =)
Как минимум, будем точно знать сермяжную правду про типы данных в ПХП :)
Я год назад пытался на работе написать модуль, который бы подставлял вместо встроенных php любые другие, определённые пользователем. Тогда оно всё так и зависло, хотя кое-какой подстановки добился, но сейчас вспомнить бы было кстати.
проще на рубях переписать аналог проекта.
На чём знаем, на том пишем :) И сколько бы люди не холиварили на чём проще, лучше и т.д. Факт остаётся фактом, что чем больше знаешь инструментов, тем лучше, быстрее и проще можно получить конечный результат.
Зная пых, я бы на нем такую систему не затевал. Нестабильно.
Сайт да, демон возможно, но не такие конструкции.
Исхожу из удобства пользования и личного опыта.
Минусующим привет)
Эмм, не понял вашего изъяснения. Если вы про то, что я делал, то изначально был готовый проект на php, надо было сделать для него такой вот финт ушами.
Ясно) Там просто с этим делом так себе. нет настолько распространенных подсистем, как rvm например. Да и в php меньшая зависимость от версий. Если только 4.x, 5.x, 5.3, 5.4, но это все можно и в коде описать при надобности без таких заморочек. Даже лучше в коде описать. Весьма портабельно.
Документация по Zend2 ужасная — лишь поверхностное описание структур.
Чтобы правильно поняли: на сайте у zend'а, а не в статье.
Большое спасибо. очень доступно и актуально, жду продолжения.
Интересно узнать у автора — вы сами используете самописные модули на c++ в своих проектах? Если да, то по возможности расскажите как и для чего?
С недавних пор да. Как использую — подключаю в PHP ini. =) Для чего — для увеличения производительности.

А если серьезно, был один класс PHP, который активно использовался в проекте. Профилирование показало, что много времени уходит именно на выполнение работы этим классом. После портирования на C++ этот участок ускорился в 2 раза, но это далеко не предел, так как оптимизации еще и близко не было.

ZE написан на C, я же привык к языкам чуть более высокого уровня. Изначально по привычке стал активно использовать std::string, std::vector, std::map и т.п. В результате получилось слишком большое количество ненужных преобразований из zval в стандартные типы C++ (так как из userspace все параметры приходят именно в zval`ах). Производительность была на уровне оригинального класса PHP. Отказавшись от использования вектора в качестве массива строк в пользу зендовской HashTable получил двукратный прирост производительности за счет сокращения ненужных операций по работе с памятью. Думаю, переезд со стандартных строк на zval`ы даст еще больший прирост, так как специфика класса такова, что он очень активно работает именно со строковыми данными. Неудобство же работы с сырыми zval`ами в качестве массивов (HashTable) я обошел, написав легкую обвеску в виде класса-массива вокруг зендовской HashTable.
> С недавних пор да. Как использую — подключаю в PHP ini. =) Для чего — для увеличения производительности.

Ну вы мне не ответ написали ) Про php.ini и пр. я бы и в документации прочитал сам, если бы не знал. «для увеличения производительности» — это вроде как всем и так уже всем вроде понято. Я тут не для холиваров и пр. Интересно суть проблемы узнать. Под вопросом «как и где» я имел ввиду реальные примеры. Просто я как-то раз думал о внедрении, но тут проблема тестирования встала, да и просто надежности.

Хочется узнать для каких именно задач вы именно вы используете.

Не знаю будет ли следующее в тему, но скажу. Я вот совершенно в очередной раз перечитывал мануал недавно наткнулся на «SplDoublyLinkedList» в структуру этого типа можно делать push объектов (это важно!) раза в 2,5 — 3 быстрее, чем в стандартные массивы.
Spl-массивы действительно работают значительно быстрее обычных. Когда заранее известен размер массива SplFixedArray вообще оказывается отличным решением.

Внедрения модуля еще не было. Класс, который мы портировали, изначально был разработан не нами, тестами он не покрыт, во всяком случае в той комплектации, в которой он предлагается для скачивания. При этом он используется уже ни один год (и не только нами, я уверен), так что о надежности кода на PHP можно не сильно волноваться.
Я написал собственные тесты, которые прогоняют некоторый объем функциональности исходного класса и моего порта, при этом производится сравнение результатов выполнения обоих классов между собой. Результаты работы оригинального класса принимаются за expected, а моего — за actual.
У меня задача была уменьшить потребление памяти программы. Она уходила именно на большое кол-во объектов > 5 млн. со свойствами и пр. (предлагаю не обсуждать зачем мне это надо было, это сейчас не важно). Так вот я реализовал простой класс-убийцу класс-заменитель на C++ как extension для php и всё было круто — память почти не кушалась, по сравнению с php, но вот уже бизнес-логику в классы было добавит сложнее. И тут я подумал — а не сделать ли мне наследника этого класса, не переобъявляя свойства cpp-класса? Сделал — и память тут же начала кушаться как раньше.

Следующая проблема — поддержка таких классов. Много знаете программистов которые смогут разобраться в этом коде?

И тут я понял — может просто стоит изолировать такие места в отдельные подпрограммы на cpp, если уж так важна скорость? На этом я и остановился. Но вообще вопрос интересный, так-то я не против ускорить узкое место, просто понимать стоит ли оно того.
Я правильно понимаю, что Вы в сишную часть перенесли только свойства объектов, а методы при этом решили реализовывать на PHP?
Да, но вот я только что подумал о том, что я не пробовал сишный класс как единственное свойство моего «бизнес» класса сделать и там всю инфу хранить — так может и отрулило бы. Правда это какой-то антипаттерн получается — объект для простого хранения инфы.
Просто я не могу понять, какой смысл хранить данные отдельно от того места, где они будут обрабатываться. Если решили хранить данные внутри расширения, то и обрабатывайте их там же. Если обрабатываете их в PHP, то и храните их в PHP. В противном же случае от создания своего расширения ничего, кроме накладных расходов Вы не поимеете. Возможно, Вам просто стоит пересмотреть архитектуру своего проекта.
Я писал, что я отказался от варианта расширений в принципе, так как обрабатывать данные внутри него — это довольно сложно, для этого нужен уже не php разработчик, а c++ программист. И тут встает вопрос — а оно надо? Может просто эту часть проекта на c++ переписать и всё будет очень быстро.

По сути вы не библиотеку для всех пишите (имею ввиду php-pg, php-redis и подобные), а я так понимаю часть бизнес логики. Вот как раз это, думаю, просто надо писать отдельно от php кода.
Если Вы имеете ввиду мой класс, то он не содержит ни грамма бизнес-логики. Это обычный шаблонизатор и его можно использовать в любом проекте. Потому, собсно, я и решил вынести его в модуль расширения.
Да, тогда я с вами солидарен.
Но это не означает, что модуль не может, в принципе, решать задачи бизнес-логики. Но безусловно, чтобы перенести бизнес-логику в C/C++ нужны навыки программирования именно на этих языках, а не на PHP. Одно только ручное управление памятью чего стоит =)

Между прочим, в коде на C доступно очень много функций, к которым все так привыкли в PHP. Они помечены сигнатурой PHPAPI в коде ZE. Есть вещи вроде php_var_dump, php_explode, php_stristr и т.д. Все с нуля писать не придется в случае чего.
Ну как-то я всё равно побаиваюсь самописные модули внедрять на работающие крупные проекты — как бы php я доверяю, а модули — это что-то за гранью добра и зла не особо распространенное, поэтому не хочется нервничать.

А сорцы шаблонизатора вы выложили куда-нибудь?
Пока еще нет. Есть некоторые мотивы. А вопрос доверия достаточно спорный — мой стаж программирования на C++ в несколько раз превышает стаж программирования на PHP. Так что своего коду на C++ я доверяю больше, например.
Я писал вручную модуль для PHP на Си где-то в 2006 году, но тогда у SWIG не было поддержки PHP. А какой смысл делать это сейчас?
Такой, что, когда PHP класс, который нужно портировать, активно работает с окружением PHP. Например, как организовать доступ к $GLOBALS в коде на C++ с использованием SWIG? Там есть какие-то бешеные примеры с мешаниной сишного и PHP кода в одном файле, но это как-то уж слишком.
Я смотрел первое время в сторону SWIG. Не вышло. Хотя, возможно, я просто не умею его готовить.
Ох, что-то у меня с родным языком сегодня проблемы… Какой уж тут PHP =)
Спасибо большое за статью, я как раз везде искал информацию об этом, но в основном крохи находил. Надеюсь скоро будет продолжение.
В институте я писал курсовую, которая была посвящена этой теме — созданию расширений для PHP на C++. Я тогда писал модуль для линейного программирования, который экспортировал в userspace одну функцию — для решения задачи симплекс-методом.

Очень жаль, что тогда не было такой статьи. Я собирал информацию по кусочкам, многого не понял и оставил многое не доведенным до правильного состояния. Очень интересная тема.
Интересно. А что за расширение-то писали?
Спасибо огромное. С нетерпением жду следующую часть.
Sign up to leave a comment.

Articles