memcache vs memached - сравниваем клиенты для PHP

Какой клиент лучше использовать при разработке на PHP - php-memcached или php-memcache? Все зависит от того, какие особенности Вам нужны (неужели?). Давайте сравним в двух аспектах - функциональность и производительность.
Функциональность
Клиентская библиотека php-memcache была разработана еще в 2004 году и сегодня существует уже довольно стабильная версия, которая используется в 99.9% проектах (использующих сервер Memcache). Большим недостатком этой библиотеки является ее ограниченные способности - она реализует только часть протокола мемкеша, и не позволяет использовать его дополнительные возможности (какие именно - чуть ниже).
Библиотека php-memcached была разработана сравнительно недавно, но уже успешно используется на некоторых крупных проектах (например, digg.com - из которого и вышла эта разработка). Самое главное ее преимущество - это полная реализация протокола, в том числе:
- CAS токены для версионирования ключей
- Обратные вызовы (callbacks)
- Метод getDelayed() позволяющий уменьшить время ожидания откладывая фактическое чтение ключей
- Поддержка бинарного протокола
- Возможность избежать сериализации используя igbinary
Производительность
Теперь давайте сравним производительность на практике.
Для этого напишем небольшой скрипт, который делает одинаковые операции с обоими клиентами:
<?
$ops = 10000;
$m = new Memcache();
$m->addServer('localhost');
$md = new Memcached();
$md->addServer('localhost', 11211);
echo "Test operations: {$ops}";
echo "<h3>get test</h3>";
$s = microtime(true);
for ( $i = 0; $i < $ops; $i++ ) $m->get( md5(rand(1000, 99999)) );
echo "Memcache: " . ($res['memcache']['set'] = microtime(true) - $s ) . "<br />";
$s = microtime(true);
for ( $i = 0; $i < $ops; $i++ ) $md->get( md5(rand(1000, 99999)) );
echo "Memcached: " . ($res['memcached']['set'] = microtime(true) - $s );
echo "<h3>set test</h3>";
$s = microtime(true);
for ( $i = 0; $i < $ops; $i++ ) $m->set(md5(rand(1000, 99999)), 2);
echo "Memcache: " . ($res['memcache']['get'] = microtime(true) - $s ) . "<br />";
$s = microtime(true);
for ( $i = 0; $i < $ops; $i++ ) $md->set(md5(rand(1000, 99999)), 2);
echo "Memcached: " . ($res['memcached']['get'] = microtime(true) - $s );
echo "<h3>delete test</h3>";
$s = microtime(true);
for ( $i = 0; $i < $ops; $i++ ) $m->delete(md5(rand(1000, 99999)));
echo "Memcache: " . ($res['memcache']['delete'] = microtime(true) - $s ) . "<br />";
$s = microtime(true);
for ( $i = 0; $i < $ops; $i++ ) $md->delete(md5(rand(1000, 99999)));
echo "Memcached: " . ($res['memcached']['delete'] = microtime(true) - $s );
echo "<h3>combined test</h3>";
$s = microtime(true);
for ( $i = 0; $i < $ops; $i++ )
{
$key = md5(rand(1000, 99999));
$m->set($key, 2);
$m->get($key);
$m->delete($key);
}
echo "Memcache: " . ($res['memcache']['combined'] = microtime(true) - $s ) . "<br />";
$s = microtime(true);
for ( $i = 0; $i < $ops; $i++ )
{
$key = md5(rand(1000, 99999));
$md->set($key, 2);
$md->get($key);
$md->delete($key);
}
echo "Memcached: " . ($res['memcached']['combined'] = microtime(true) - $s );
Как видно, скрипт просто выполняет основные операции сохранения, чтения и удаления ключей 10 тыс. раз и замерает их время для каждого клиента.
Результаты работы теста
Как видно из графика, производительность клиента php-memcache почти втрое выше, чем php-memcached. Следует учесть, что показатели при работе с бинарным протоколом почти не отличалась по времени от ASCII протокола.
Обновление
Благодаря внимательному читателю этого блога удалось выяснить, что сильные отличия в показателях тестов связаны с конкретными версиями и настройками библиотек. Проверка на других платформах дает отличие в производительности не более 10%.
В качестве вывода следует сказать, что клиент php-memcache лучше использовать, если функционала приложению полностью хватает (лучше, т.к. он быстрее). Если нужны расширенные возможности, то нужно использовать php-memcached. Но в этом случае нужно учесть понижение производительности.
Хотя важно заметить: даже не смотря на трехкратное различие в скорости работы, операции общения с сервером Memcache обычно занимают доли процента от времени исполнения приложения. Различие в скорости работ библиотек может быть заметно только при массовой работе с кешом, или же на огромных объемах данных.


Дякую за статтю. Тепер буде стимул і самому розібратися з memcache
Я бы добавил еще тест на мультигет
Здравствуйте!
Ваш тест на Ubuntu Netbook Remix:
Test operations: 10000
get test
Memcache: 3.74332213402
Memcached: 3.32582402229
set test
Memcache: 3.64596199989
Memcached: 2.93430399895
delete test
Memcache: 2.82469391823
Memcached: 3.00117897987
combined test
Memcache: 6.8338830471
Memcached: 7.90108919144
Разницы в 3 раза не наблюдается.
@vasa_c
Давайте сравним, укажите версии библиотек и самого сервера.
@Den Golotyuk
Ubuntu 9.10
PHP 5.3.2-dev
PHP Extension 20090626
Zend Extension 220090626
php_memcache version 2.2.5
php_memcached version 1.0.1
libmemcached version 0.31
Memcached 1.2.8
memcached 1.4.2
php-memcache 2.2.5
php-memacached 1.0.2
PHP 5.2.11
libmemcached 0.40
И того, различия в сервере и версии PHP, что скорее всего не может дать такой разницы. Я попробую провести тесты на других серверах и опубликую результаты.
Разве что php-memcached в 1.0.2 значительно ухудшился по сравнению с 1.0.1
Я тоже постараюсь сегодня проверить на FreeBSD
@vasa_c
Я нашел довольно интересную закономерность. Похоже что результаты тестов сильно искажены внутренней проблемой библиотеки memcached (судя по всему этой конкретной версии). Буду благодарен, если проведете тест на своей сторое: в одном случае соединение устанавливается с IP (127.0.0.1) в другом с доменным именем (localhost).
И как меняются ваши результаты в зависимости от этого?
Я не заметил у себя существенных изменений.
Кстати, rand() и md5() тяжеловаты, лучше их из тестируемого цикла выкинуть.
$keys = array();
for ($i = 0; $i < $ops; $i++) {
$key = md5(rand(1000, 9999));
$val = 2;
$keys[$key] = $val;
}
$s = microtime(true);
#for ( $i = 0; $i set(md5(rand(1000, 99999)), 2);
foreach ($keys as $key => $val) {
$m->set($key, $val);
}
echo “Memcache: ” . ($res['memcache']['get'] = microtime(true) - $s ) . “”;
$s = microtime(true);
#for ( $i = 0; $i set(md5(rand(1000, 99999)), 2);
foreach ($keys as $key => $val) {
$md->set($key, $val);
}
echo “Memcached: ” . ($res['memcached']['get'] = microtime(true) - $s );
В этом случае тесты ускоряются практически вдвое.
Но относительные скорости такие же.
FreeBSD 6.3-STABLE
PHP 5.3.2-dev
php_memcache 3.0.4
php_memcached 1.0.1
libmemcached 0.31
memcached 1.2.8
результаты для обоих библиотек снова различаются слабо
Извиняюсь за назойливость.
Написал свой тест - http://blgo.ru/t/blog/090527/mc/
Memcache Memcached
set-new 191 174
set-exists 185 173
get-exists 177 167
get-empty 170 159
delete-exists 182 164
delete-empty 174 160
Числа - микросекунды на один запрос.
@vasa_c
Спасибо! Важные результаты, т.к. php-memcached показывает лучшую производительность.