-
-
Save php-cpm/ac7fd10c84894320e364e7e54ccc93b6 to your computer and use it in GitHub Desktop.
first benchmark is redis | |
<?php | |
$redis = new Redis(); | |
$redis->connect('127.0.0.1', 6379); | |
for ($i = 0; $i < 100; $i++) { | |
$start = microtime(true); | |
for ($j = 0; $j < 10000; $j++) { | |
$key = sprintf("key:%05d", $j); | |
$redis->pipeline(); | |
/* GET or SET */ | |
if (rand() % 2 == 0) { | |
$redis->set($key, rand()); | |
} else { | |
$redis->get($key); | |
} | |
} | |
$time = microtime(true)-$start; | |
printf("%6d req/sec\n", $j/$time); | |
} |
using non-pipeline mode I got result
9733 req/sec
<?php
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);
for ($i = 0; $i < 100; $i++) {
$start = microtime(true);
for ($j = 0; $j < 10000; $j++) {
$key = sprintf("key:%05d", $j);
/* GET or SET */
if (rand() % 2 == 0) {
$redis->set($key, rand());
} else {
$redis->get($key);
}
}
$time = microtime(true)-$start;
printf("%6d req/sec\n", $j/$time);
}
redis extension info
Redis Support => enabled
Redis Version => 3.1.4
Available serializers => php, igbinary
ALL MY MISTAKE!
I used php 7.1.19 + opcache + xdebug opened
after I comment out xdebug extension I ran again and got
25707 req/sec compare to 9733 req/sec
1456659 req/sec compare to 14940 req/sec
benchmark using predis
pipeline 765286 req/sec 52.5%
non-pipeline 20015 req/sec 77.8%
$ composer require predis/predis
<?php
require 'vendor/autoload.php';
$redis = new Predis\Client();
$redis->connect('127.0.0.1', 6379);
for ($i = 0; $i < 100; $i++) {
$redis->pipeline(function ($redis) {
$start = microtime(true);
for ($j = 0; $j < 10000; $j++) {
$key = sprintf("key:%05d", $j);
/* GET or SET */
if (rand() % 2 == 0) {
$redis->set($key, rand());
} else {
$redis->get($key);
}
}
$time = microtime(true)-$start;
printf("%6d req/sec\n", $j/$time);
});
}
after install hiredis && phpiredis
pipeline 876277 req/sec
non-pipeline 24854 req/sec
HOW TO
brew install hiredis
brew tap php-cpm/php
brew install php71-phpiredis
memcache vs memcached
<?php
$m = new Memcached();
$m->addServer('localhost', 11211);
for ($i = 0; $i < 100; $i++) {
$start = microtime(true);
for ($j = 0; $j < 10000; $j++) {
$key = sprintf("key:%05d", $j);
/* GET or SET */
if (rand() % 2 == 0) {
$m->set($key, rand(), 3600);
} else {
$m->get($key);
}
}
$time = microtime(true)-$start;
printf("%6d req/sec\n", $j/$time);
}
30733 req/sec
<?php
$avg = [];
$m = new Memcache();
$m->addServer('localhost', 11211);
for ($i = 0; $i < 20; $i++) {
$start = microtime(true);
for ($j = 0; $j < 10000; $j++) {
$key = sprintf("key:%05d", $j);
/* GET or SET */
if (rand() % 2 == 0) {
$m->set($key, (object)[rand()], 0, 3600);
} else {
$m->get($key);
}
}
$time = microtime(true)-$start;
$avg[] = intval($j/$time);
printf("%6d req/sec\n", $j/$time);
}
echo array_sum($avg) / count($avg) . " req/sec avg";
23784 req/sec
php-memcached is 29% faster than php-memcache
apcu
<?php
for ($i = 0; $i < 100; $i++) {
$start = microtime(true);
for ($j = 0; $j < 10000; $j++) {
$key = sprintf("key:%05d", $j);
/* GET or SET */
if (rand() % 2 == 0) {
apcu_store($key, rand(), 3600);
} else {
apcu_fetch($key);
}
}
$time = microtime(true)-$start;
printf("%6d req/sec\n", $j/$time);
}
without socket connection apcu cache always faster than redis or memcached
1747710 req/sec
tmp file benchmark
<?php
// modify code from https://medium.com/@dylanwenzlau/500x-faster-caching-than-redis-memcache-apc-in-php-hhvm-dcd26e8447ad
function cache_set($key, $val) {
$val = var_export($val, true);
// HHVM fails at __set_state, so just use object cast for now
$val = str_replace('stdClass::__set_state', '(object)', $val);
// Write to temp file first to ensure atomicity
$tmp = "/tmp/cache/$key." . uniqid('', true) . '.tmp';
file_put_contents($tmp, '<?php $val = ' . $val . ';', LOCK_EX);
rename($tmp, "/tmp/cache/$key");
}
function cache_get($key) {
@include "/tmp/cache/$key";
return isset($val) ? $val : false;
}
$avg = [];
for ($i = 0; $i < 100; $i++) {
$start = microtime(true);
for ($j = 0; $j < 10000; $j++) {
$key = sprintf("key:%05d", $j);
/* GET or SET */
if (rand() % 2 == 0) {
cache_set($key, rand());
} else {
cache_get($key);
}
}
$time = microtime(true)-$start;
$avg[] = intval($j/$time);
printf("%6d req/sec\n", $j/$time);
}
8476 req/sec
check for avg
-
use same program
-
change cache type
-
change cache data
- object data (object)[rand()]
- array data [rand()]
- string data rand()
-
run benchmark again and again
<?php
$avg = [];
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);
for ($i = 0; $i < 100; $i++) {
$start = microtime(true);
for ($j = 0; $j < 10000; $j++) {
$key = sprintf("key:%05d", $j);
$redis->pipeline();
/* GET or SET */
if (rand() % 2 == 0) {
$redis->set($key, (object)[rand()]);
} else {
$redis->get($key);
}
}
$time = microtime(true)-$start;
$avg[] = intval($j/$time);
printf("%6d req/sec\n", $j/$time);
}
echo array_sum($avg) / count($avg) . " req/sec avg";
<?php
/*
* using unix socket server make connection 2x faster
* server redis.conf edit:
* unixsocket /tmp/redis.sock
* unixsocketperm 777
*/
$avg = [];
$redis = new Redis();
$redis->connect('/tmp/redis.sock');
for ($i = 0; $i < 100; $i++) {
$start = microtime(true);
for ($j = 0; $j < 10000; $j++) {
$key = sprintf("key:%05d", $j);
/* GET or SET */
if (rand() % 2 == 0) {
$redis->set($key, (object)[rand()]);
} else {
$redis->get($key);
}
}
$time = microtime(true)-$start;
$avg[] = intval($j/$time);
printf("%6d req/sec\n", $j/$time);
}
echo array_sum($avg) / count($avg) . " req/sec avg";
cache | object | array | string |
---|---|---|---|
php-ext-apcu | 797465 | 1102939.18 | 1722482.74 |
php-ext-redis pipeline | 1621555.16 | 1787449.6 | 1740069.4 |
predis+php-ext-phpiredis pipeline | 133997.95 | 125891.63 | 137244.45 |
php-ext-redis non-pipeline | 24788.3 | 25784.4 | 25462.75 |
php-ext-redis non-pipeline unix socket | 43581.2 | 44764.79 | 44441.15 |
predis+php-ext-phpiredis non-pipeline (json_encode/serialize) |
23838.1 | 24831.65 | 24202.25 |
php-ext-memcached | 28619.35 | 28633.25 | 29881.5 |
php-ext-memcache | 25440.25 | 24316.9 | 26490.4 |
based on this report we suggest people use
- php-ext-memcached as cache driver and memcached as cache server
- use php-ext-redis if you want to use pipeline, predis is too slow here
- choose either predis or php-ext-redis is ok for normal cache use
- php-ext-apcu is far more speedy, it's a good point to use it as cache to boost your program
even more hard sence
<?php
$avg = [];
for ($i = 0; $i < 100; $i++) {
$start = microtime(true);
for ($j = 0; $j < 10000; $j++) {
$redis = new Redis();
$redis->pconnect('127.0.0.1', 6379, 1, 'x');
$key = sprintf("key:%05d", $j);
$redis->pipeline();
/* GET or SET */
if (rand() % 2 == 0) {
$redis->set($key, (object)[rand()]);
} else {
$redis->get($key);
}
$redis->close();
}
$time = microtime(true)-$start;
$avg[] = intval($j/$time);
printf("%6d req/sec\n", $j/$time);
}
echo array_sum($avg) / count($avg) . " req/sec avg";
redis pconnect reuse 21710.55
use strace to analise sys call sudo dtruss -c php redis.php
predis
CALL COUNT
bsdthread_register 1
connect 1
fchmod 1
ftruncate 1
getentropy 1
getpid 1
getrlimit 1
getsockopt 1
getuid 1
shm_open 1
sigprocmask 1
thread_selfid 1
write 1
csops 2
fstatat64 2
fstatfs64 2
getegid 2
gettid 2
issetugid 2
openat_nocancel 2
unlink 2
geteuid 3
socket 3
getdirentries64 4
sysctl 4
fcntl_nocancel 6
madvise 6
pread 12
mprotect 17
readlink 17
read_nocancel 19
access 28
lseek 41
open 42
close 45
sigaction 45
close_nocancel 49
open_nocancel 52
lstat64 54
munmap 64
ioctl 73
fcntl 74
stat64 86
mmap 104
getattrlist 132
fstat64 146
recvfrom 8390
sendto 8390
poll 8391
predis calls more recvfrom
sendto
so it's a little slower than others
php-ext-redis
bsdthread_register 1
connect 1
fchmod 1
ftruncate 1
getentropy 1
getpid 1
getrlimit 1
getsockopt 1
getuid 1
shm_open 1
sigprocmask 1
thread_selfid 1
csops 2
fstatat64 2
fstatfs64 2
getegid 2
gettid 2
issetugid 2
openat_nocancel 2
unlink 2
access 3
geteuid 3
socket 3
getdirentries64 4
sysctl 4
fcntl_nocancel 5
madvise 6
pread 12
lstat64 13
open 13
close 16
fcntl 16
mprotect 17
readlink 17
read_nocancel 19
munmap 35
lseek 41
sigaction 45
close_nocancel 48
open_nocancel 51
stat64 56
fstat64 58
ioctl 73
mmap 75
getattrlist 132
sendto 1596
setsockopt 1597
recvfrom 1598
poll 6382
php-ext-memcached
bsdthread_register 1
connect 1
fchmod 1
ftruncate 1
getentropy 1
getpid 1
getrlimit 1
getsockopt 1
getuid 1
setsockopt 1
shm_open 1
sigprocmask 1
thread_selfid 1
write 1
csops 2
fstatat64 2
fstatfs64 2
getegid 2
gettid 2
issetugid 2
openat_nocancel 2
socket 2
unlink 2
access 3
geteuid 3
getdirentries64 4
sysctl 4
fcntl_nocancel 5
madvise 6
pread 12
lstat64 13
open 13
close 15
fcntl 17
mprotect 17
readlink 17
read_nocancel 19
munmap 35
lseek 41
sigaction 45
close_nocancel 48
open_nocancel 51
stat64 56
fstat64 58
ioctl 73
mmap 75
getattrlist 132
poll 2550
sendto 2552
recvfrom 5103
php connect to redis using a lot of poll
when memcached using recvform code recvfrom(0x4, 0x7FC86509E2B8, 0x2004) = -1 Err#35
which means Resource deadlock avoided
php-ext-apcu
CALL COUNT
bsdthread_register 1
exit 1
fchmod 1
ftruncate 1
getentropy 1
getpid 1
getrlimit 1
getuid 1
shm_open 1
sigprocmask 1
socket 1
thread_selfid 1
csops 2
fstatat64 2
fstatfs64 2
getegid 2
gettid 2
issetugid 2
openat_nocancel 2
unlink 2
access 3
geteuid 3
getdirentries64 4
sysctl 4
fcntl_nocancel 5
pread 12
lstat64 13
open 13
fcntl 14
close 16
mprotect 17
readlink 17
read_nocancel 19
lseek 41
sigaction 45
open_nocancel 50
close_nocancel 51
stat64 56
fstat64 58
ioctl 73
mmap 75
write 101
getattrlist 132
munmap 140
madvise 232
apcu memory operation calling madvise
, munmap
, etc.
i only got 14940 req/sec using pipeline