Семафоры и общая память System V в PHP
22.10.2008
Казалась бы, обсуждаемая мной тема, мало кого волнует, но попытаемся разобраться в скрытых возможностях php, и чем эти возможности могут быть полезны разработчику. Тема PHP заезжена до дыр , о плюсах и минусах его сказано много , да вот проблема в том, что если недовольные хорошо знают все минусы данного языка программирования, то те, кому он нравится, плохо знают как можно оптимально его использовать. К сожалению, это очень портит репутацию PHP . Но тема не об этом.
Давайте представим простейшую задачу. Требуется сохранить информацию одним скриптом и считать его другим. Задача простейшая и многие сразу же крикнут: «Файлы, БД, COOKIE и т.д.». Давайте подумаем об эффективности данных подходов.
Начнем с файлов. Кратковременное сохранение данных в файле является мультиплатформенным решением, и даже в какой-то степени простым. Но с точки зрения оптимальности — это плохой вариант. Во-первых, сомнительно, что он окажется в кеше жесткого диска , значит считываться данные будут напрямую с носителя. Соответственно, жесткий диск может быть занят и своими более важными делами — значит получение данных будет задержано. Во-вторых, добавим к этому приоритетность задач, и тогда поймем, что временный файлик ваще важен только для вас , а для ОС он является самым последним в очереди.
Про Базы Данных можно долго спорить. Во-первых, надо еще соединиться с сервером БД, а это занимает очень много времени и ресурсов , ибо сервер БД — это отдельное приложение. Во-вторых, сервер БД может быть и так загружен, а тут еще вы со своим маленьким текстом.... Проблема не в том, что текст маленький, а в том, что надо инициализировать множество операций, чтобы этот текст передать и сохранить его в структуру таблиц БД. Лучше пусть БД занимается теми делами, в которых она лучше всего подходит: для хранения и выборки данных, а не для кратковременного хранения для передачи текста.
Про COOKIE скажу проще, во-первых, ограничение в 4 кб (хотя для краткого текста даже в UTF-8 этого предостаточно). Во-вторых, куки еще надо передать, а это несет в себе еще кучу операций. Да еще и данные идут через клиентскую часть, поэтому они могут быть сворованы или подделаны, или и то, и другое в порядке очередности =) . Да и куки могут быть отключены вааще, значит еще надо определять - включены они или нет, а это еще куча дополнительных тактов процессора будет съедено впустую.
Но если подумать — какой инструмент для ОПЕРАТИВНОЙ передачи данных мы забыли? По выделенному слову можно догадаться, что оперативного, т.е того источника, который быстро может предоставить информацию. Речь идет банально о системной памяти, которая чаще всего находится в области оперативной памяти, либо в виде файла подкачки, что быстрее в силу ряда причин (таких как структуры данных, приоритетность операций IO).
Но причем тут PHP ? А притом, что в PHP реализована работа с системной памятью на уровне ОС . Далее опишу, как можно использовать данную «примочку».
Для примера создадим два простейших скрипта: shm_write.php и shm_read.php, и посмотрим на их примере работу общей памяти. Задача состоит в том, чтобы записать информацию в память одним скриптом, а потом получить и вывести её другим скриптом.
--------------
shm_write.php
--------------
<?php
//Создадим ключ-идентификатор общей памяти (например 2008)
define('SHM_KEY', 2008);
//Создадим ключ-идентификатор хранящейся в памяти переменной (например 1430)
define('SHM_VAR_KEY', 1430);
//Укажем размер памяти выделяемой для хранения (для примера возьмем 1 кб)
define('SHM_MEMLIMIT', 1024);
//создаем идентификатор на общую память
$shm_mem = shm_attach(SHM_KEY, SHM_MEMLIMIT);
//сохраняем определенный текст в память
shm_put_var($shm_mem, SHM_VAR_KEY, 'Hello World');
//удаляем идентификатор на общую память (удаляется только идентификатор!)
shm_detach($shm_mem);
?>
------------------------------
shm_read.php
------------------------------
<?php
//Создадим ключ-идентификатор общей памяти (тот который мы указали в shm_write.php - 2008)
define('SHM_KEY', 2008);
//Создадим ключ-идентификатор хранящейся в памяти переменной ( тот который мы указали в shm_write.php - 1430)
define('SHM_VAR_KEY', 1430);
//создаем идентификатор на общую память
$shm_memory = shm_attach(SHM_KEY);
//обращаемся к сегменту памяти код ключом равным SHM_VAR_KEY и получаем хранимый текст
$message = shm_get_var($shm_memory, SHM_VAR_KEY);
//удаляем из памяти переменную под ключом SHM_VAR_KEY
shm_remove_var($shm_memory, SHM_VAR_KEY);
//удаляем общую память
shm_remove($shm_memory);
//выводим результат
echo $message;
?>
Запустим вначале shm_write.php - скрипт, который сохранит в сегмент памяти текст . А позднее запустим shm_read.php — скрипт, который прочитает текст из сегмента памяти.
На выводе мы получим «Hello World».
Всего пару строк кода, а мы смогли передать некую информацию из одного скрипта в другой, не задействовав ни внешний источник, ни файловую систему, ни базу данных.
Специального тестирования я проводить не стал, но судя по показаниям xDebug+KCacheGrind при симулированной нагрузке в 60% на одноядерный процессор, и при находящемся практически без дела жестаке, показало, что работа с системной памятью намного быстрее + не задевает тормозную файловую систему, да и хлама меньше. Я не стал проверять на системе с постоянной чтение-запись с жестким диском, но явно будет еще медленнее. Конечно, тест неявный, но зная, как работает системная память в unix системах, легко догадаться, что такая конструкция будет быстрее.
Так неужели нет минусов с использованием общей памяти в PHP ? Конечно, есть. Во-первых, это не кроссплатформенное решение (на Windows-серверах не будет работать). Во-вторых, надо не забывать память вычищать, иначе данные сохраненные в сегментах памяти останутся там до ближайшего рестарта сервера. Ну и в-третьих, администраторы не всегда любят использование общей памяти в нуждах скриптах, и для общих хостинговых систем поддержка SystemV может быть отключена, либо урезана по квоте.
С другой стороны, использование общей памяти SystemV (а также возможности установки прав доступа на сегмент, который по умолчанию равен 0666 — на чтение-запись) и механизма семафоров позволит реализовать монопольный доступ к сегментам памяти определенным скриптом. А это уже мощный контроллер против банальных backdoor и всяческих эксплоитов. Плюсом ко всему этому есть возможность передачи информации между процессами, не задействуя файловую систему.
О механизме семафоров я постараюсь написать в близжайшее время, а также привести примеры с совместным использованием семафоров и общей памяти.
____________________________
Похожие записи:
- Flash сайт - от экстаза до разочарования, или основные тенденции на фронте мирового флешестроения
- Каким должен быть программист
Теги: KCacheGrind, MySQL, php, system v, xDebug, бд, семафоры

25.10.2008 в 14:09
Интересная статья. А как на счет поддержки System V на различных хостинг-площадках? Боюсь многие рубят эту возможность..
Ждем про семафоры!
[Ответить]
Alligator Reply:
Октябрь 27th, 2008 at 10:31
К сожалению на некоторых серверах возможность использования общей памяти отключена (на строгих хостинг-компаниях всеже разрешено - но строго протоколируется). Считаю что для быстрых систем , а также вообще там где это возможно - использовать такую возможность надо обязательно
[Ответить]
Ivan_Fedorovich Reply:
Ноябрь 5th, 2008 at 01:13
кстати тоже постоянно сталкиваюсь с темой зарубки System V на хостингах.....
[Ответить]
09.11.2008 в 00:54
Ну что там с семафорами, очень интересная тема!
[Ответить]
04.02.2009 в 03:25
Интересная статья - а system v реально используется на ваших проектах?
[Ответить]