Pull to refresh

phpDaemon и runkit: новый уровень

PHP *
Сегодня я поведаю о новых вкусных плюшках phpDaemon, в том числе предоставленных PHP-модулем runkit.

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


История runkit


PECL/runkit — весьма примечательный PHP-модуль, история которого положена женщиной-программистом Sara Golemon в далеком августе 2005 года. Его назначение — позволить в процессе выполнения скрипта изменять константы, переопределять функции и классы, и выполнять в PHP другие манипуляции сродни черной магии…
Однако, проект был очень сырой, требовал много времени для исправления багов и поддержания совместимости с новыми версиями PHP. И Sara потеряла интерес к разработке проекта, по причинам о которых мы можем лишь догадываться. Но она сделала главное — показала что всё это возможно — дело техники. После этого вносили изменения pajoye, johannes, sfox, sebastian, mlively, и другие. Правда например за весь 2007 год было всего 4 коммита, и модуль продолжал жестко глючить и отставать от основной ветки PHP. Было несколько попыток форка со стороны сторонних разработчиков, но лишь одна на мой взгляд увенчалась успехом.
Наш соотечественник Дмитрий Зенович (dzenovich) дал ему новую жизнь, по адресу github.com/zenovich/runkit: The runkit that works!

Обновление кода на лету


Раньше при включении в phpDaemon опции --auto-reload=5s, демон раз в 5 секунд проверял даты модификации всех подключенных PHP-файлов, и при их изменении уходил в плавный перезапуск. Теперь же достаточно включить --auto-reimport и вместо плавного перезапуска, измененный файл будет импортирован прямо в живой процесс. Это значительно упрощает жизнь, надо сказать. Спасибо за это Дмитрию Зеновичу! (и немножко мне, за то что теребил).

Runkit_Sandbox


Помимо манипуляций с классами, константами, и функциями, runkit позволяет создавать песочницу. Выглядит вот так:

$sandbox = new Runkit_Sandbox(array(
    'safe_mode'        => TRUE,
....
    'output_handler'   => array($this,'out')
));
$sandbox->call_user_func(function() {
 		echo "Hello World!";
});


При этом код выполняемый в песочнице не может повлиять на родительный контекст, и Fatal error/Parse error не вызовет падения основного скрипта. Также можно задавать для песочницы любые ini-опции.

Переопределение родных PHP-функций


Runkit позволяет переопределять не только пользовательские, но и родные сишные PHP-функции. На данный момент phpDaemon перегружает header() и register_shutdown_function() и направляет вызовы в соответствующие метода текущего запроса.

С функцией create_function() отдельная история. Возможно кто-то не знает подноготную данной функции, но в действительности она представляет собой вот это:
function create_function($args,$code)
{
 static $c = 0;
 $name = "\x00lambda_".$c++;
 eval('function '.$name.'('.$args.') {'.$code.'}');
 return $name;
}

То есть она создает самую обычную и заурядную функцию и возвращает ее название строкой. Само собой, ни о каком удалении ненужных лямбда-функций речи не идет, они живут до смерти скрипта. Сам я не обращал внимание на эту проблему т.к. давно не использую create_function, а вот Илья Кантор (algo) в своей статье (True FastCGI для PHP — миграция и тесты) обратил на это внимание и предложил запоминать названия всех лямбда-функций созданных в процессе выполнения запроса, и в конце очищать. Это решение подходит для его задачи, но в целом для phpDaemon оно по понятным причинам неприемлемо.
Поэтому я выдумал другое решение, на мой взгляд более изящное и универсальное. Моя create_function() возвращает объект DestructableLambda, в деструкторе которого происходит удаление лямбда-функции через runkit. Вдобавок имеется LRU-кеш, который хранит наиболее часто компилируемые лямбда-функции, что снижает затраты на компиляцию. Исходник.

Если у вас появились идеи какие еще функции можно улучшить, будем рады услышать.

The конец


Ну вот пожалуй и всё. Всем спасибо за внимание.

Github: kakserpom/phpdaemon
Homepage: http://phpdaemon.net
Group: groups.google.com/group/phpdaemon
Tags:
Hubs:
Total votes 72: ↑63 and ↓9 +54
Views 3.7K
Comments Comments 61