原贴:http://www.javaeye.com/article/80095
iunknown 发表于 2007-05-15 14:43 浏览3242次
关键字:
C++ libevent memcached 内存池 平衡树 性能测试
发布在
C++语言 圈子 加入在
C/C++专栏 专栏
推荐 收藏 进入论坛
great,望尽快提供性能测试对比:) 从猜测角度来说,感觉使用new/delete和平衡树的开销会大一些
测试环境: CPU:intel T2300 1.66G ,1G MEM HOST:windows xp + vmware 5.5.1 + RedHatLine 7.2 ( linux 2.4.18-3 ) vmware 的内存设置为 128M 测试之前,先重启了 windows xp,再重启 vmware。测试期间不上网,不运行其他程序。 T2300 是双核 CPU ,但是在 vmware 中使用 top 命令只能看到一个 CPU 。
测试工具: com/danga/MemCached/test/MemCachedBench 由于使用 jdk1.4,所以用的不是最新的包,而是 java_memcached-release_1.3.2.tar.gz 。 MemCachedBench 经过少量修改,以便在命令行指定不同的端口。
测试模型: 1.限定 memcached 和 spcached 在测试中将保存同样多的 items 数目。memcached 通过内存使用量来限定 items 数目,spcached 直接有参数来限定 items 数目。 2.MemCachedBench 的步骤是先增加 五十万 个 item 到服务器(实际真正保存的数目为291984),然后再查询这 五十万 个 item 。分别计算插入的时间和查询的时间。 3.运行一次测试之后,通过 stats 命令查询 memcached 和 spcached 的内部状态。 4.由于分配给 vmware 的内存少,测试 memcached 的时候,停止 spcached ;测试 spcached 的时候,停止 memcached 。 5.memcached , spcached 和 测试工具 都运行在同一个操作系统中。
软件版本: memcached 1.2.0 spcached svn revision 5 + spserver 0.3 + spdict 0.2
具体的测试数据见后面,先来看结果。
从客户端计算测试的结果(处理速度之比,spcached/memcached): 插入 162758 / 229266 = 71 % 查询 201934 / 284856 = 71 %
从服务器计算测试的结果(使用 cpu 时间之比,spcached/memcached): rusage_user 1.330000 / 0.770000 = 1.72 rusage_system 38.670000 / 75.630000 = 0.51
即从客户端来看,spcached 只达到 memcached 71% 的性能。 从服务器的 cpu 使用角度来看,spcached 的 system 时间只有 memcached 的一半,user 时间是 memcached 的 1.72 倍。
测试的环境使用的是 linux 2.4.18-3 ,使用 LinuxThreads 。spcached 的 user 时间比 memcached 多,应该是由于 LinuxThreads 进行调度耗费了不少时间。另外 hash table 和 BalancedTree 的操作也是属于 user 时间,BalancedTree 的操作比 hash table 慢。 出乎意料,memcached 的 system 时间居然是 spcached 的两倍。没仔细看 memcached 的代码,不知道是什么原因。
结合客户端和服务器两方面的结果来看,令人非常迷茫。服务器费时少的程序,对应的客户端用的时间居然反而长。 要解释这种情况,看来要进一步看看操作系统方面的书。
最初希望 spcached 能达到 memcached 80% 的性能,现在只能达到 70% ,也算是一个还能接受的结果。
代码
rusage_user 32u:32u Accumulated user time for this process (seconds:microseconds) rusage_system 32u:32u Accumulated system time for this process (seconds:microseconds)
<script type="text/javascript">render_code();</script>
代码
bash-2 .05a$ ./memcached -m 128 bash-2 .05a$ java com/danga/MemCached/test/MemCachedBench 500000 0 11211 500000 sets: 162758ms 500000 gets: 201934ms bash-2 .05a$telnet 0 11211 STAT rusage_user 0.770000 STAT rusage_system 75.630000
<script type="text/javascript">render_code();</script>
代码
bash-2 .05a$ ./spcached -c 291984 bash-2 .05a$ java com/danga/MemCached/test/MemCachedBench 500000 0 11216 500000 sets: 229266ms 500000 gets: 284856ms bash-2 .05a$ telnet 0 11216 STAT rusage_user 1.330000 STAT rusage_system 38.670000 bash-2 .05a$ top PID USER PRI NI SIZE RSS SHARE STAT %CPU %MEM TIME COMMAND 15854 svn 15 0 112M 96M 66952 S 0.0 77.9 0 :21 spcached
<script type="text/javascript">render_code();</script>
引用
出乎意料,memcached 的 system 时间居然是 spcached 的两倍。没仔细看 memcached 的代码,不知道是什么原因。
查看了 MemCachedBench 的源代码之后,发现了问题所在。
代码
pool.setInitConn(100 ); pool.setMinConn(100 );
<script type="text/javascript">render_code();</script> 测试工具在开始测试的时候就发起了 100 个连接到服务器,而测试过程中只会用到一个连接。由于测试环境的 linux 版本低,所以使用的还是 select ,而不是 epoll 。epoll 对于这种只有少量连接活跃的情况能够处理的很好,但是 select 却是相反,因此导致服务器在 select 上消耗了大量的时间。 spcached 比 memcached 消耗少的原因在于 spcached 对于不活跃的连接设置了 60 秒的超时时间,而 memcached 是永不超时的。所以 spcached 在前 60 秒受到 99 个不活跃连接的干扰,而 memcached 是一直受干扰。
改 MemCachedBench 的代码如下,重新测试
代码
pool.setInitConn(1 ); pool.setMinConn(1 );
<script type="text/javascript">render_code();</script> 从客户端计算测试的结果(处理速度之比,spcached/memcached): 插入 132917 / 204055 = 65 % 查询 150149 / 220507 = 68 %
从服务器计算测试的结果(使用 cpu 时间之比,spcached/memcached): rusage_user 0.800000 / 0.470000 = 1.7 rusage_system 34.050000 / 53.730000 = 0.63
测试结果是 memcached 更快了。
代码
./memcached -m 96 bash-2 .05a$ java com/danga/MemCached/test/MemCachedBench 500000 0 11211 500000 sets: 132917ms 500000 gets: 150149ms bash-2 .05a$ telnet 0 11211 STAT rusage_user 0.470000 STAT rusage_system 53.730000 bash-2 .05a$ top PID USER PRI NI SIZE RSS SHARE STAT %CPU %MEM TIME COMMAND 16587 liusf 15 0 99 .8M 80M 2800 S 0.0 65.3 0 :54 memcached
<script type="text/javascript">render_code();</script>
代码
bash-2 .05a$ ./spcached -c 185808 bash-2 .05a$ java com/danga/MemCached/test/MemCachedBench 500000 0 11216 500000 sets: 204055ms 500000 gets: 220507ms bash-2 .05a$ telnet 0 11216 STAT rusage_user 0.800000 STAT rusage_system 34.050000 bash-2 .05a$ top PID USER PRI NI SIZE RSS SHARE STAT %CPU %MEM TIME COMMAND 16563 svn 15 0 74916 73M 608 S 0.0 59.1 2 :07 spcached
<script type="text/javascript">render_code();</script>
使用 cprof 对 spcached 做 profiler ,其中对 key 进行比较的函数占用差不多 60% 的时间。
代码
bash-2 .05a$ cprof spcached cmon.out | more Function Name calls func% func(ms) f+c% f+c(ms) 0 4930875599.984 11095618832560 100.000 225023 compare__19SP_CacheItemHandlerPCvT1 32320411 35.035 78837 57.750 129949
<script type="text/javascript">render_code();</script>
代码
int xxx :: compare( ... ) { ...... return strcmp( i1->getKey(), i2->getKey() ); }
<script type="text/javascript">render_code();</script> 如果使用 hash table ,会减少很多对这个函数的调用。
改用和 memcached 同样的 hash table 之后,数据如下:
代码
Function Name calls func% func(ms) f+c% f+c(ms) 0 13660645568.442 11095652346241 100.000 81223 hashCode__19SP_CacheItemHandlerPCv 2600000 8.435 6851 13.449 10923 compare__19SP_CacheItemHandlerPCvT1 785604 2.392 1942 3.983 3235
<script type="text/javascript">render_code();</script>
代码
bash-2 .05a$ java com/danga/MemCached/test/MemCachedBench 500000 0 11216 500000 sets: 193644ms 500000 gets: 207668ms bash-2 .05a$ telnet 0 11216 STAT rusage_user 0.220000 STAT rusage_system 27.780000 bash-2 .05a$ top PID USER PRI NI SIZE RSS SHARE STAT %CPU %MEM TIME COMMAND 19315 svn 15 0 77164 75M 608 S 0.0 60.9 1 :57 spcached
<script type="text/javascript">render_code();</script>
高手问个问题。
memcached 对 cache 对象 大小有什么限制 。
我在程序中 如果对象的大小 超过255kb 就出错。
(SERVER_ERROR object too large for cache) [50:30.597] - ++++ error storing data in cache for key: test_key7 -- length: 1048603 [50:30.597] - SERVER_ERROR object too large for cache [50:30.597] - ++++ serializing for key: test_key8 for class: [I [50:30.701] - ++++ memcache cmd (result code): set test_key8 8 0 1048603 (SERVER_ERROR object too large for cache) [50:30.702] - ++++ error storing data in cache for key: test_key8 -- length: 1048603 [50:30.703] - SERVER_ERROR object too large for cache [50:30.703] - ++++ serializing for key: test_key9 for class: [I [50:30.805] - ++++ memcache cmd (result code): set test_key9 8 0 1048603 (SERVER_ERROR object too large for cache) [50:30.806] - ++++ error storing data in cache for key: test_key9 -- length: 1048603 [50:30.806] - SERVER_ERROR object too large for cache
memcached现在可以./configure --enable-threads,用-t参数指定threads数量。
引用
memcached 对 cache 对象 大小有什么限制 。
我在程序中 如果对象的大小 超过255kb 就出错。
从 error message 来看,出错的时候,size 不是 255kb 哦,而是
引用
[50:30.597] - ++++ error storing data in cache for key: test_key7 -- length: 1048603
1M = 1048576 ,这里显示的是 1048603 ,超过 1M 了。
这里有说明 memcached 的限制是 1M 。 http://lists.danga.com/pipermail/memcached/2006-October/002986.html
引用
The maximum size is 1 megabyte. It can be increased; I believe there was
a patch (against the old 1.1.12 version) to do it. The trick is that
memcached's memory manager allocates memory in 1MB chunks, so increasing
the maximum is not just a matter of changing a "maximum object size"
setting somewhere. But it is certainly doable.