使用本地的环境测试10万次和 100万次 缓存的读写,测试环境和结果如下。
环境
1 2 3 4 | <code>Win7 x64 AMD7750双核 内存8G
Apache 2.4.9
PHP 5.5.12 ts vc11
memcache 2.2.7 </code>
|
登录后复制
登录后复制
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 | <?php
function convert( $size )
{
$unit = array ( 'b' , 'kb' , 'mb' , 'gb' , 'tb' , 'pb' );
return @ round ( $size / pow(1024, ( $i = floor (log( $size , 1024)))), 2) . ' ' . $unit [ $i ];
}
function cacheFile( $key )
{
$dir = 'cache' ;
if (! is_dir ( $dir ) && ! mkdir ( $dir )) {
throw new Exception( " can't make dir $dir" );
}
$filepath = $dir . DIRECTORY_SEPARATOR . sprintf( '%x' , crc32( $key ));
if (!( file_exists ( $filepath ) && ( $data = file_get_contents ( $filepath )) && ! empty ( $data ))) {
$data = date ( 'Y-m-d H:i:s' );
file_put_contents ( $filepath , $data );
}
return $data ;
}
function cacheMem( $key )
{
$mem = new Memcache();
$mem ->connect( '127.0.0.1' , 11211);
$data = $mem ->get( $key );
if ( empty ( $data )) {
$data = date ( 'Y-m-d H:i:s' );
$mem ->set( $key , $data );
}
return $data ;
}
$t1 = microtime(true);
$i = 0;
$limit = 1000 * 100;
$data = null;
while ( $i < $limit ) {
$data = cacheMem( $i );
$i ++;
}
$timeUse = microtime(true) - $t1 ;
$arr = [
'cost' => sprintf( '%.7fs' , $timeUse ),
'mem' => convert(memory_get_usage())
];
var_dump( $arr );
|
登录后复制
登录后复制
结果 1万次
1 2 3 | <code> 花费时间 内存耗费
File 1.9 sec 250kb
Memcache 11 sec 250kb</code>
|
登录后复制
登录后复制
结果 10万次
1 2 3 4 | <code> 花费时间 内存耗费
File 94s 251.18KB
Memcache 超时120s 报错
</code>
|
登录后复制
登录后复制
Memcache 10万次测试失败,报错内容如下
1 2 3 4 | <code>Warning: Memcache::connect(): in D:\localhost\speed.php on line 37
Warning: Memcache::get(): No servers added to memcache connection in D:\localhost\speed.php
Warning: Memcache::set(): No servers added to memcache connection in D:\localhost\speed.php on line 41
Fatal error: Maximum execution time of 120 seconds exceeded in D:\localhost\speed.php on line 38</code>
|
登录后复制
登录后复制
结论
memcache
用来做缓存却还没有 直接File文件缓存快,之所以做这个测试,是因为面试的时候我回答自己并没有使用这个memcache 来做缓存,直接使用File文件缓存,结果直接被技术官认定为是初级程序员
。但我通过这样的测试,虽然是在win下面,可为什么Memcahe性能还不如File ?
还是说我测试的方式存在错误?
2015-8-21 20:52:17
改进后,真的速度快了N倍! 10万毫无压力。17.18 sec
265KB内存
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | <code> function cacheMem( $key )
{
static $mem = null;
if ( $mem === null) {
$mem = new Memcache();
$mem ->connect( '127.0.0.1' , 11211);
}
$data = $mem ->get( $key );
if ( empty ( $data )) {
$data = date ( 'Y-m-d H:i:s' );
$mem ->set( $key , $data );
}
return $data ;
}
</code>
|
登录后复制
登录后复制
回复内容:
使用本地的环境测试10万次和 100万次 缓存的读写,测试环境和结果如下。
环境
1 2 3 4 | <code>Win7 x64 AMD7750双核 内存8G
Apache 2.4.9
PHP 5.5.12 ts vc11
memcache 2.2.7 </code>
|
登录后复制
登录后复制
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 | <?php
function convert( $size )
{
$unit = array ( 'b' , 'kb' , 'mb' , 'gb' , 'tb' , 'pb' );
return @ round ( $size / pow(1024, ( $i = floor (log( $size , 1024)))), 2) . ' ' . $unit [ $i ];
}
function cacheFile( $key )
{
$dir = 'cache' ;
if (! is_dir ( $dir ) && ! mkdir ( $dir )) {
throw new Exception( " can't make dir $dir" );
}
$filepath = $dir . DIRECTORY_SEPARATOR . sprintf( '%x' , crc32( $key ));
if (!( file_exists ( $filepath ) && ( $data = file_get_contents ( $filepath )) && ! empty ( $data ))) {
$data = date ( 'Y-m-d H:i:s' );
file_put_contents ( $filepath , $data );
}
return $data ;
}
function cacheMem( $key )
{
$mem = new Memcache();
$mem ->connect( '127.0.0.1' , 11211);
$data = $mem ->get( $key );
if ( empty ( $data )) {
$data = date ( 'Y-m-d H:i:s' );
$mem ->set( $key , $data );
}
return $data ;
}
$t1 = microtime(true);
$i = 0;
$limit = 1000 * 100;
$data = null;
while ( $i < $limit ) {
$data = cacheMem( $i );
$i ++;
}
$timeUse = microtime(true) - $t1 ;
$arr = [
'cost' => sprintf( '%.7fs' , $timeUse ),
'mem' => convert(memory_get_usage())
];
var_dump( $arr );
|
登录后复制
登录后复制
结果 1万次
1 2 3 | <code> 花费时间 内存耗费
File 1.9 sec 250kb
Memcache 11 sec 250kb</code>
|
登录后复制
登录后复制
结果 10万次
1 2 3 4 | <code> 花费时间 内存耗费
File 94s 251.18KB
Memcache 超时120s 报错
</code>
|
登录后复制
登录后复制
Memcache 10万次测试失败,报错内容如下
1 2 3 4 | <code>Warning: Memcache::connect(): in D:\localhost\speed.php on line 37
Warning: Memcache::get(): No servers added to memcache connection in D:\localhost\speed.php
Warning: Memcache::set(): No servers added to memcache connection in D:\localhost\speed.php on line 41
Fatal error: Maximum execution time of 120 seconds exceeded in D:\localhost\speed.php on line 38</code>
|
登录后复制
登录后复制
结论
memcache
用来做缓存却还没有 直接File文件缓存快,之所以做这个测试,是因为面试的时候我回答自己并没有使用这个memcache 来做缓存,直接使用File文件缓存,结果直接被技术官认定为是初级程序员
。但我通过这样的测试,虽然是在win下面,可为什么Memcahe性能还不如File ?
还是说我测试的方式存在错误?
2015-8-21 20:52:17
改进后,真的速度快了N倍! 10万毫无压力。17.18 sec
265KB内存
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | <code> function cacheMem( $key )
{
static $mem = null;
if ( $mem === null) {
$mem = new Memcache();
$mem ->connect( '127.0.0.1' , 11211);
}
$data = $mem ->get( $key );
if ( empty ( $data )) {
$data = date ( 'Y-m-d H:i:s' );
$mem ->set( $key , $data );
}
return $data ;
}
</code>
|
登录后复制
登录后复制
错在你不该在while里写connect...哪有每次都去连接的?
首先,建立一个到Memcached的TCP连接的开销肯定要比打开一个本地文件大,而在你的cli测试中,反复建立了上万次连接,而在Web上(比如PHP-FPM,MOD_PHP),可以使用到Memcached的持久连接,也就是一个PHP-FPM工作进程保持一个Memcached的长连接,用于处理多个不同的请求:
http://php.net/manual/zh/memcached.construct.php
1 2 | <code><?php
$mc = new Memcached( 'story_pool' );</code>
|
登录后复制
其次,操作系统会缓存本地文件到内存(就是Linux上的buffers/cache),读性能肯定是不错的,但是频繁的写性能肯定没有Memcached好,因为Memcached读写操作都保证在内存中完成。
另外,Memcached能实现分布式(由客户端实现,比如PHP的PECL扩展memcached),这个也是本地文件缓存不具备的优势。Memcached的分布式体现在将不同的键保存到不同的服务器上。
http://php.net/manual/zh/memcached.addserver.php
注意:PHP有两个针对Memcached的PECL扩展,一个叫做memcache,一个叫做memcached:
http://php.net/manual/zh/intro.memcache.php
http://php.net/manual/zh/intro.memcached.php
其中基于libmemcached的扩展memcached实现了分布式,而memcache则没有实现。
上面说的对,你的测试方法是错误的,因为memcache已经达到最大连接数了,所以报错
不过我想知道你用的是什么磁盘,SSD or FIO or SAS,IOPS是多少;说明一下,memcache中key最大值为250B,value最大值为1M,一般情况下value大于1M,也就是超过memcache中page的大小时候,memcache也就无能为力了,不过你可以通过更改源代码来实现或者换redis(value最大值512M)
其实也不必测试,memcache数据全部放在内存中,然而内存和磁盘不是一个级别,我们可以分析一下:
1纳秒等于10亿分之一秒,= 10 ^ -9 秒
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | <code>Numbers Everyone Should Know
L1 cache reference 读取CPU的一级缓存 0.5 ns
Branch mispredict(转移、分支预测) 5 ns
L2 cache reference 读取CPU的二级缓存 7 ns
Mutex lock/unlock 互斥锁\解锁 100 ns
Main memory reference 读取内存数据 100 ns
Compress 1K bytes with Zippy 1k字节压缩 10,000 ns
Send 2K bytes over 1 Gbps network 在1Gbps的网络上发送2k字节 20,000 ns
Read 1 MB sequentially from memory 从内存顺序读取1MB 250,000 ns
Round trip within same datacenter 从一个数据中心往返一次,ping一下500,000 ns
Disk seek 磁盘搜索 10,000,000 ns
Read 1 MB sequentially from network 从网络上顺序读取1兆的数据 10,000,000 ns
Read 1 MB sequentially from disk 从磁盘里面读出1MB 30,000,000 ns
Send packet CA->Netherlands->CA 一个包的一次远程访问 150,000,000 ns</code>
|
登录后复制
我们关注一下内存和磁盘的访问速度,上面是指随机访问,那么相差1000 000倍,但如果是顺序访问的话大约为 7倍
楼主应该好好看看设计模式,你的面试官没说错你。。。可能初级程序员都懂得缓存对象吧。。谁会每次循环都连接一次memcached?
如果用file存的话, 100w 请求,你去看下服务器的硬盘读写。服务器早挂掉了。
磁盘IO延迟和资源开销和文件系统开销也挺大得。
我只想问哈楼主是用什么测出PHP运行时间的?
事实证明 你就是1、2年的初级。 但是当时面试官否认掉你 没跟你讲明原因吗?
还有给你 也是给所有人一个忠心的建议,切忌不要太浮躁! 或是自我膨胀,以当前时间为节点来看,自己永远是井底之蛙,不经历一些事情有可能不会明白。