Comments 64
Какой из клиентов использовали? И почему?
Были какие то неявности, странности и баги, кроме приведения кодировок?
Были какие то неявности, странности и баги, кроме приведения кодировок?
Какой из клиентов использовали? И почему?
выбран php-handlersocket по той причине, что это враппер над libhandlersocket.
Если сравнивать с производительностью HS клиента, то за счет медлительности самого РНР, все нативные клиенты, написанные на нем, проигрывают в производительности врапперам. Далеко ходить не надо: сравнимаем производительность мемкешед и редис клиентов. Какой используешь ты и почему?
Про PEAR клиента — та же история, только с боку.
Какой используешь ты и почему?
Пока никакой, не было подходящей задачи. На будующее интересуюсь. А то обычно для новых технологий: куча разных библиотек, 1 вообще не работает, во 2-ой встроенное кэширование, которое нельзя сбросить, в 3-ей 100500 багов и тишина, остальные худо-бедно работают, если знать правильные заклинания и иметь набитые шишки.
не поверю, что не используешь мемкеш!
Я думал ты про handlersocket. Для memcached использую memcache, ибо меньше глючит.
ну про шишки ты пррравильно подметил
+1 про шишки. Иногда офигеваешь, и только после многочасовых танцев с бубном понимаешь причину бага. Взять хотя бы авто-сериализацию в php-memcached после 2000 символов.
можно подробнее?
Конечно, вот тут "Автосжатие в php-memcached после 20 000 символов при выключенном сжатии" подробнее.
при выдачи nginx напрямую из мемкеша (ngx_memcached) есть небольшой патчик
который анализирует код возврата memcached, и если там хранилась «сжатая» информация, то выставляет соответствующие заголовки.
рекомендую+ съэкономите на памяти.
который анализирует код возврата memcached, и если там хранилась «сжатая» информация, то выставляет соответствующие заголовки.
рекомендую+ съэкономите на памяти.
а вообще статья зачетная, я про это тоже не знал.
Вообще-то в самом пхп-мемкешед модуле много магии.
Вообще-то в самом пхп-мемкешед модуле много магии.
или скорее всего в libmemcached
Андрей, ты потерял на мемкешед пол дня, я почти три: habrahabr.ru/blogs/php/74643/
Были какие то неявности, странности и баги, кроме приведения кодировок?Долго провозился с кодировками. Первое время думал что бага, отписал автору.
Решил эту проблему, только после применения нативного протокол через телнет. хотел выяснить, кто виноват: враппер, либа или ограничена возможность HS. Сперва думал, что это бага.
Ну, если быть откровенным, я часть функционала, связанного с memcached отлаживаю, используя телнет. Как-то Хабросообществом была недооценена моя статья, в которой я по шагам расписал, как я отлавливал багу в libmemcached. А вот по рассылкам php-hiload да и в самом Сообществе проскакивали похожие баги падения memcached. Так что хочу обратить внимание, что знание нативного протокола всегда помогает в отладке.
что осталось за кадром: тестируется функционал композитных ключей.
см комментарий один из последних комментариев про багу.
А у меня очень большой вопрос: HandlerSocket позволяет осуществить сортировку результата? Или тут тупо PK/K lookup, а сортировать на клиенте, теряя выигранное (и даже проигрывая еще больше)?
Даже хрен с ней, сортировкой, HandlerSocket отдаст записи в том же порядке, в каком были указаны ID в запросе? Типа queryMulti (ID=3,5,1,9) — записи вернутся отсортированые по ключу, по запросу или неопределено?
Отвечу сразу на два вопроса.
1. Сортировка записей в HandlerSocket не предусмотрена.
2. При Multi-Get записи будут возвращаться в том порядке, в котором были указаны ID в запросе. Вот пример:
______________________
Текст подготовлен в Редакторе Блогов от © SoftCoder.ru
А вот результат:
______________________
Текст подготовлен в Редакторе Блогов от © SoftCoder.ru
1. Сортировка записей в HandlerSocket не предусмотрена.
2. При Multi-Get записи будут возвращаться в том порядке, в котором были указаны ID в запросе. Вот пример:
-
- <?php
- // connect
- $hs = new HandlerSocket('127.0.0.1', 9998);
- if($hs) {
- print 'Connected to HandlerSocket<br/>';
- } else {
- print 'Can not connect<br/>';
- die();
- }
- //index
- $index = $hs->openIndex(
- 1,
- 'mysql',
- 'user',
- HandlerSocket::PRIMARY,
- 'Host,User,Select_priv'
- );
- if($index) {
- print 'Index opened<br/>';
- } else {
- print 'Can not open index<br/>';
- echo $hs->getError(), PHP_EOL;
- die();
- }
- $id = rand(1,1000);
- // find
- //$result = $hs->executeSingle(1, '=', array($id), 1, 0);
-
- // Чтение данных Multi-Get (find по тому же индексу)
- $retval = $hs->executeMulti(
- array(
- array(1, '=', array('localhost'), 1, 0),
- array(1, '=', array('%'), 1, 0),
- array(1, '=', array('127.0.0.1'), 1, 0)
- )
- );
-
- var_dump($retval);
-
-
______________________
Текст подготовлен в Редакторе Блогов от © SoftCoder.ru
А вот результат:
-
- Connected TO HandlerSocket<br/>Index opened<br/>array(3) {
- [0]=>
- array(1) {
- [0]=>
- array(3) {
- [0]=>
- string(9) "localhost"
- [1]=>
- string(16) "debian-sys-maint"
- [2]=>
- string(1) "Y"
- }
- }
- [1]=>
- array(1) {
- [0]=>
- array(3) {
- [0]=>
- string(1) "%"
- [1]=>
- string(6) "daobay"
- [2]=>
- string(1) "Y"
- }
- }
- [2]=>
- array(1) {
- [0]=>
- array(3) {
- [0]=>
- string(9) "127.0.0.1"
- [1]=>
- string(4) "root"
- [2]=>
- string(1) "Y"
- }
- }
- }
-
-
______________________
Текст подготовлен в Редакторе Блогов от © SoftCoder.ru
Спасибо, это отличная новость. Тогда можно отсортировать и выбрать ID в нужном порядке посредством SQL, а данные уже через HandlerSocket.
UFO just landed and posted this here
Очень даже не экзотический, а вполне работающий.
Это обобщенный подход, дающий лучшую среднюю производительность, чем сложная сортировка и выемка данных в одном запросе. Т.е. вместо одного запроса всегда два. В моем случае второй запрос можно заменить на HandlerSocket.
$IDs = SELECT id FROM megatable WHERE a=10 AND b>9000 AND c BETWEEN 1111 AND 100500 ORDER BY a DESC, c ASC, g ASC
$Data = SELECT * FROM megatable WHERE ID IN ($IDs) ORDER BY FIND_IN_SET(ID, $IDs) ASC
Это обобщенный подход, дающий лучшую среднюю производительность, чем сложная сортировка и выемка данных в одном запросе. Т.е. вместо одного запроса всегда два. В моем случае второй запрос можно заменить на HandlerSocket.
$IDs = SELECT id FROM megatable WHERE a=10 AND b>9000 AND c BETWEEN 1111 AND 100500 ORDER BY a DESC, c ASC, g ASC
$Data = SELECT * FROM megatable WHERE ID IN ($IDs) ORDER BY FIND_IN_SET(ID, $IDs) ASC
То же самое касается JOIN'ов. Собираем нужные нам id'шники по всяким разным условиям, сортируем как хотим, а непосредственно загрузку сущностей делаем через HS. По сравнению с JOIN думаю это даст хороший выигрыш на таблицах больших объемов.
UFO just landed and posted this here
Ok, посмотрите план SQL-запроса с JOIN и без.
Пусть t1 — полное время выполнения простого запроса (включая сетевые задержки),
t2 — то же самое для сложного запроса (с JOIN'ами),
t3 — общее время время выполнения запросов HS по получению сущностей.
Наша идея в том, что t2 > t1 + t3.
Пусть t1 — полное время выполнения простого запроса (включая сетевые задержки),
t2 — то же самое для сложного запроса (с JOIN'ами),
t3 — общее время время выполнения запросов HS по получению сущностей.
Наша идея в том, что t2 > t1 + t3.
UFO just landed and posted this here
А не могли бы сделать тест производительности, чтобы можно было сравнить быстродействие расширения, PEAR пакета и HSPHP? Спасибо!!!
РЕАR точно делать не буду, так как ./configure --without-pear
а HS & php-handlersocket сделаю. Выиигрыш в копейки, но все же, у кого большие нагрузки — приятно.
а HS & php-handlersocket сделаю. Выиигрыш в копейки, но все же, у кого большие нагрузки — приятно.
сделал тест,
дописал в конец темы
дописал в конец темы
0.0003 микросекунды на запрос? Это что-то типа 3 млрд. запросов в секунду? :) Можете попробовать с помощью DBench протестировать, оно там умеет на автомате базу случайными данными забивать (см. example) и графики строить. Для вашего случая там надо будет только DBench_Test_Abstract отнаследовать с переопрелением protected function test() на обращение к базе через Handler Socket.
Что-то типа 3 млрд. запросов в секунду — это что-то типа 1 такта процессора на запрос? :) Ясно же, что не может быть такой производительности.
Это был риторический вопрос, сарказм т.е. :)
Автор пишет:
Я потому и переспрашиваю, может в данном случае имеются ввиду «секунды» и нужно подправить топик.
Автор пишет:
время грязное в микросекундах, с учетом на инклуды и инстанс класса
0.005791
Я потому и переспрашиваю, может в данном случае имеются ввиду «секунды» и нужно подправить топик.
Время без инклудов и инстансов, чисто одна выборка по PK
$t1 = microtime();
$retval = $hs->executeSingle(2, '=', array('60187'));
echo microtime()-$t1, PHP_EOL;
$t1 = microtime();
$res = $rs->select('=','60187');
echo microtime()-$t1, PHP_EOL;
У вас там явная ошибка: вместо microtime() нужно писать microtime(true).
Немного смущает отсутствие документации на php-hanlpersocket
Возможно, немного поможет $ php --re handlersocket
и чем же?
не более чем Class synopsis¶
HandlerSocket {
/* Constants */
const HandlerSocket::PRIMARY;
/* Methods */
__construct ( string $host, int $port, [ array $options ])
public bool openIndex ( int $id, string $db, string $table, string $index, string $fields )
public mixed executeSingle ( int $id, string $op, array $fields [, int $limit, int $skip, strint $modop, array $values ] )
public mixed executeMulti ( array $requests )
public int executeUpdate ( int $id, string $op, array $fields, array $values [, int $limit, int $skip ] )
public int executeDelete ( int $id, string $op, array $fields [, int $limit, int $skip ] )
public bool executeInsert ( int $id, array $values )
public string getError ( void )
}
не более чем Class synopsis¶
HandlerSocket {
/* Constants */
const HandlerSocket::PRIMARY;
/* Methods */
__construct ( string $host, int $port, [ array $options ])
public bool openIndex ( int $id, string $db, string $table, string $index, string $fields )
public mixed executeSingle ( int $id, string $op, array $fields [, int $limit, int $skip, strint $modop, array $values ] )
public mixed executeMulti ( array $requests )
public int executeUpdate ( int $id, string $op, array $fields, array $values [, int $limit, int $skip ] )
public int executeDelete ( int $id, string $op, array $fields [, int $limit, int $skip ] )
public bool executeInsert ( int $id, array $values )
public string getError ( void )
}
вообщее-то я в таких случаях лезу в исходники. Но тут исходники показали, что все параметры тупо передаются на сервер через libh..s…
т.е. копаем логику в граблях самого HS
т.е. копаем логику в граблях самого HS
мои планы:
написать утилитку, аналог redis-cli,
чтоб лучше отлаживать, проверять ключи. Все-таки telnet -это вчерашний день.
есть желание (нет времени) доработать php-handlersocket в сторону:
— фильтрация данных, чтоб это делать не средствами РНР
— сюда же возможность использования простых шаблонов аля '%'
— JOIN рекордсетов. Пока думаю как лучше сделать.
Сегодня перевел статистику (очень тяжелый update на 17 мин) на HS. Выполняется чуть более нескольких минут. Все в режиме тестирования.
написать утилитку, аналог redis-cli,
чтоб лучше отлаживать, проверять ключи. Все-таки telnet -это вчерашний день.
есть желание (нет времени) доработать php-handlersocket в сторону:
— фильтрация данных, чтоб это делать не средствами РНР
— сюда же возможность использования простых шаблонов аля '%'
— JOIN рекордсетов. Пока думаю как лучше сделать.
Сегодня перевел статистику (очень тяжелый update на 17 мин) на HS. Выполняется чуть более нескольких минут. Все в режиме тестирования.
Готов принять участие в тестировании, если что.
Нативная сортировка + фильтрация в расширении, это клёво. Всё лучше выносить за уровень php. А как планируется реализовать JOINы? Через серию запросов в ресширении, и возвращении полного набора данных (уже сджоиненного) в php?
Нативная сортировка + фильтрация в расширении, это клёво. Всё лучше выносить за уровень php. А как планируется реализовать JOINы? Через серию запросов в ресширении, и возвращении полного набора данных (уже сджоиненного) в php?
с джоинами все просто:
1) делаем выборку по ключу T1.key1,
2) делаем выборку по ключу T2.key2 = T1.key1,
выборки у нас отсортивованы по клюючам.
3) начинаем итерировать полученный рекордсет T1 и класть его в массив,
одновременно сливая его с рекордсетом T2.
Возможные грабли или подводные камни:
мы не можем вытащить весь рекодсет простым запросом (SELECT *… WHERE region_id=1). Мы обязаны указать значение LIMIT. Соответственно нужно вытягивать либо с заданным LIMIT очень большое число, либо порциями.
1) делаем выборку по ключу T1.key1,
2) делаем выборку по ключу T2.key2 = T1.key1,
выборки у нас отсортивованы по клюючам.
3) начинаем итерировать полученный рекордсет T1 и класть его в массив,
одновременно сливая его с рекордсетом T2.
Возможные грабли или подводные камни:
мы не можем вытащить весь рекодсет простым запросом (SELECT *… WHERE region_id=1). Мы обязаны указать значение LIMIT. Соответственно нужно вытягивать либо с заданным LIMIT очень большое число, либо порциями.
хотелось бы что-то вроде executeMulti('ID', 'sql', 'SELECT id FROM foo WHERE bar=0')
чтобы избежать промежуточного хранения значений ключей в памяти средствами пхп, очень уж избыточно по 60 лишних байт на каждый элемент массива.
чтобы избежать промежуточного хранения значений ключей в памяти средствами пхп, очень уж избыточно по 60 лишних байт на каждый элемент массива.
что пока не выяснено, но хотелось бы:
public mixed executeSingle ( int $id, string $op, array $fields [, int $limit, int $skip, strint $modop, array $values ] )
последние два параметра: strint $modop, array $values, судя по описанию представляют собой аналог getset (или взять и уничтожить). Однако, у меня пока это не получилось.
public mixed executeSingle ( int $id, string $op, array $fields [, int $limit, int $skip, strint $modop, array $values ] )
последние два параметра: strint $modop, array $values, судя по описанию представляют собой аналог getset (или взять и уничтожить). Однако, у меня пока это не получилось.
это в ответ на комментарий habrahabr.ru/blogs/nosql/113040/#comment_3626332 к вопроосу о багах
Да, вспомнил про одну багу:
когда отлаживался, то сбросил телнет по kill -9
последующие запуски скрипта приводили к его зависанию.
приходилось перезапускать мускуль.
когда отлаживался, то сбросил телнет по kill -9
последующие запуски скрипта приводили к его зависанию.
приходилось перезапускать мускуль.
Еще бы сравнение с любым из PDO/mysqli/mysqlnd с использованием prepared statements.
тесты есть в презенташке моего доклада на AddConf
www.slideshare.net/akalend/handdler-socket-in-the-addconf
сейчас нет времени писать топики, работаю над другими интересными проектами,
есть положительные результаты, но выкладывать как статьи еще рано.
www.slideshare.net/akalend/handdler-socket-in-the-addconf
сейчас нет времени писать топики, работаю над другими интересными проектами,
есть положительные результаты, но выкладывать как статьи еще рано.
Sign up to leave a comment.
Первый опыт работы с Handler Socket & php_handlersocket