Pull to refresh

Расширение PHP для асинхронного ввода-вывода POSIX

Reading time3 min
Views5.6K

Бэкграунд



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

Речь идёт о расширении PECL eio, предоставляющем интерфейс к библиотеке libeio.



libeio



На всякий случай, приведу небольшое описание libeio. Это библиотека С для которая запускает системные вызовы(в основном POSIX) в отдельных потоках. Цель библиотеки — полностью неблокирующее ПО, которое может пригодиться на игровых серверах, как пишет автор библиотеки, М.Леман:
"...in a game server, you would not want to freeze for a few seconds just because the server is running a backup and you happen to call readdir."


Т.е. такие вызовы, как open, read, write, close, readahead, truncate, rename, sendfile, statvfs и т.п. в libeio запускаются в отдельных потоках.

Документация libeio непосредственно не отвергает Windows. Написано, что если соответствующего вызова в библиотеке нет, то libeio эмулирует этот вызов. Однако, в исходном коде практически нет ничего для того, чтобы собрать (обычным образом) код в Windows. У меня такое чувство, что автор подумывал о поддержке Windows, но впоследствии отказался от этой идеи.

Расширение eio



В расширении выполняются вызовы libeio. Для того, чтобы инициировать выполнение ряда вызовов libeio, нужно циклически вызывать eio_poll(). Для этого в PHP экспортирована одноимённая функция. Дополнительно реализован цикл событий в виде функции eio_event_loop(), IPC которой выполнен на основе семафоров. При желании пользователь может выполнить собственный цикл событий существующими средствами PHP(Например, при помощи глобальных переменных[лучше только в CLI] или тех же семафоров с использованием расширения Semaphore).

Документация: http://www.php.net/eio.

Установка



libeio:

$ touch ~/.cvspass
$ cvs -z3 -d :pserver:anonymous@cvs.schmorp.de/schmorpforge co libeio
$ cd libeio
$ ./autogen.sh
$ ./configure
$ make
$ su -
# make install


eio:
$ wget 'http://pecl.php.net/get/eio' -O eio.tgz
$ tar xzvf eio.tgz && cd eio-*
$ phpize
$ ./configure --with-eio # further optional parameters(--enable-eio-debug recommended for first use) ...
$ make && make test
$ su -
# make install


После этого записываем в конфиг php.ini
extension=eio.so
перезапускаем Веб-сервер, если это не CLI.

Если в Gentoo возникают проблемы вроде
libtool: Version mismatch error. This is libtool 2.4, but the
libtool: definition of this LT_INIT comes from an older release.
libtool: You should recreate aclocal.m4 with macros from libtool 2.4
libtool: and run autoconf again.
make: *** [libevent.lo] Error 63


то следующие команды помогут:

$ phpize
$ aclocal && libtoolize --force && autoreconf
$ ./configure --with-eio # further optional parameters(--enable-eio-debug recommended for first use) ...
$ make
# дальше как обычно


Вы также можете воспользоваться пакетами libeio, которые я собрал для следующих дистрибутивов:
Debian_6.0 i586, x86_64
RedHat_RHEL-6 i586, x86_64
openSUSE_11.4 i586, x86_64
xUbuntu_10.04 i586, x86_64
xUbuntu_11.10 i586, x86_64
К сожалению, автор libeio предлагает лишь CVS.

Однако, eio можно установить проще:
# pecl install eio # для stable
# pecl install eio-beta # для beta
# pecl install eio-alpha # для alpha


В качестве альтернативы, можно взять самое свежее из SVN:
$ svn co https://svn.php.net/repository/pecl/eio/trunk eio && cd eio
# pecl install --force package.xml

Последнюю команду нужно дать с правами root

Наконец



Спасибо за внимание. Буду рад любым предложениям по дополнению/изменению API.

P.S.
Это eio далось непросто.

UPDATE


В результате работы с автором libevent:
добавлено: event_priority_set
добавлено: поддержка числовых дескрипторов в event_set
добавлено: поддержка числовых дескрипторов в event_buffer_new

Собственно в eio добавлена поддержка файлового дескриптора, который может быть исопльзован для эффективной связки с libevent, правда, пока только в SVN(см. ниже).

Связка с приоритетами(не прямо таки реальный пример, но кому нужно напишет реальный;):
<?php
function my_eio_poll($fd, $events, $arg) {
/* Some libevent regulation might go here .. */
if (eio_nreqs()) {
eio_poll();
}
/* .. and here */
}

function my_nop_cb($d, $r) {
var_dump($r); var_dump($d);
}

$base = event_base_new();
$event = event_new();

$fd = eio_get_event_stream();
var_dump($fd);

eio_nop(EIO_PRI_DEFAULT, "my_nop_cb", "nop data");
/* some other eio_* calls here ... */

// set event flags
event_set($event, $fd, EV_READ /*| EV_PERSIST*/, "my_eio_poll", array($event, $base));

// Set event priorities
event_base_priority_init($base, 10);

// set event base
event_base_set($event, $base);

// This one is my patch to libevent. Tony should apply it soon
echo "setting priority...\n";
var_dump(event_priority_set($event, 2));

// enable event
event_add($event);

// start event loop
event_base_loop($base);

/* The same kind of stuff is available via buffered libevent API*/
?>


SVN:

svn.php.net/repository/pecl/libevent/trunk
svn.php.net/repository/pecl/eio/trunk
Tags:
Hubs:
If this publication inspired you and you want to support the author, do not hesitate to click on the button
Total votes 36: ↑34 and ↓2+32
Comments38

Articles