MemCached 压力测试
关键字: MemCachedMemCached安装完成后,进行了压力测试,主要参考了MemCached的javaclient的 类com.danga.MemCached.test.MemCachedTest。它的类主要问题是没有一个总的处理能力的描述。我进行了改写,提供了get和put的总吞吐量的汇总。
测试环境如下,
服务器:RedHat9, 512内存,P4内存,跑2个MemCached实例,运行memcached-1.2.1
客户端:单独一台机器,和服务器在一个局域网,100M网络带宽,运行java_memcached-release_1.5.1, jdk5.0
测试代码:
- import com.danga.MemCached.MemCachedClient;
- import com.danga.MemCached.SockIOPool;
- public class TestMemCache {
- static SockIOPool pool;
- static int threads; // 运行的测试线程数
- static int runs; // 每个线程运行的次数
- static int size; // 设置到memcache中的数据包大小,单位k
- static Integer myLock;// 锁定以下计数器
- static long putTimes = 0; // put总时间,单位微秒
- static long getTimes = 0; // get总时间,单位微秒
- /**
- * @param args
- */
- public static void main(String[] args) {
- String[] serverlist = { "192.168.0.56:11211", "192.168.0.56:11212" };
- // initialize the pool for memcache servers
- pool = SockIOPool.getInstance();
- pool.setServers(serverlist);
- pool.setInitConn(5);
- pool.setMinConn(5);
- pool.setMaxConn(50);
- pool.setMaintSleep(30);
- pool.setNagle(false);
- pool.initialize();
- if (args.length < 3) {
- System.out.println("用法:TestMemCache 启动线程数 每线程执行测试数量 测试数据大小(k)");
- System.exit(1);
- }
- threads = Integer.parseInt(args[0]);
- runs = Integer.parseInt(args[1]);
- size = 100 * Integer.parseInt(args[2]);
- myLock = new Integer(threads);
- for (int i = 0; i < threads; i++) {
- Thread thread = new WorkerThread();
- thread.start();
- }
- }
- private static class WorkerThread extends Thread {
- // 构造函数
- WorkerThread() {
- }
- public void run() {
- // get client instance
- MemCachedClient mc = new MemCachedClient();
- mc.setCompressEnable(false);
- mc.setCompressThreshold(0);
- // get object to store
- int[] obj = new int[size];
- for (int i = 0; i < size; i++) {
- obj[i] = i;
- }
- String[] keys = new String[runs];
- for (int i = 0; i < runs; i++) {
- keys[i] = "test_key" + i;
- }
- for (int i = 0; i < runs; i++) {
- mc.delete(keys[i]);
- }
- long startTime = System.currentTimeMillis();
- for (int i = 0; i < runs; i++) {
- mc.set(keys[i], obj);
- }
- long time = System.currentTimeMillis() - startTime;
- synchronized (myLock) {
- putTimes += time;
- }
- startTime = System.currentTimeMillis();
- for (int i = 0; i < runs; i++) {
- mc.get(keys[i]);
- }
- time = System.currentTimeMillis() - startTime;
- synchronized (myLock) {
- getTimes += time;
- myLock--;
- if (myLock.equals(0)) {
- System.out.println("测试完成! 启动线程数:" + threads
- + ", 每线程执行测试数量: " + runs + ", 测试数据大小(byte):" + size);
- System.out.println("put处理时间:" + putTimes
- + "微秒,处理put速度: 每秒 " + runs * threads * 1000 / putTimes
- + " 次");
- System.out.println("get处理时间:" + getTimes
- + "微秒,处理get速度: 每秒 " + runs * threads * 1000 / getTimes
- + " 次");
- pool.shutDown();
- }
- }
- }
- }
- }
测试结果:
测试完成! 启动线程数:1, 每线程执行测试数量: 1000, 测试数据大小(byte):1024
put处理时间:2515微秒,处理put速度: 每秒 789 次
get处理时间:1266微秒,处理get速度: 每秒 789 次
测试完成! 启动线程数:2, 每线程执行测试数量: 1000, 测试数据大小(byte):1024
put处理时间:3595微秒,处理put速度: 每秒 1471 次
get处理时间:2734微秒,处理get速度: 每秒 1471 次
测试完成! 启动线程数:3, 每线程执行测试数量: 1000, 测试数据大小(byte):1024
put处理时间:6250微秒,处理put速度: 每秒 1846 次
get处理时间:4829微秒,处理get速度: 每秒 1846 次
测试完成! 启动线程数:4, 每线程执行测试数量: 1000, 测试数据大小(byte):1024
put处理时间:8673微秒,处理put速度: 每秒 2063 次
get处理时间:7858微秒,处理get速度: 每秒 2063 次
测试完成! 启动线程数:5, 每线程执行测试数量: 1000, 测试数据大小(byte):1024
put处理时间:10655微秒,处理put速度: 每秒 2352 次
get处理时间:10625微秒,处理get速度: 每秒 2352 次
测试完成! 启动线程数:6, 每线程执行测试数量: 1000, 测试数据大小(byte):1024
put处理时间:14702微秒,处理put速度: 每秒 2042 次
get处理时间:16844微秒,处理get速度: 每秒 2042 次
测试完成! 启动线程数:7, 每线程执行测试数量: 1000, 测试数据大小(byte):1024
put处理时间:18766微秒,处理put速度: 每秒 2502 次
get处理时间:20265微秒,处理get速度: 每秒 2502 次
测试完成! 启动线程数:8, 每线程执行测试数量: 1000, 测试数据大小(byte):1024
put处理时间:23828微秒,处理put速度: 每秒 2586 次
get处理时间:25062微秒,处理get速度: 每秒 2586 次
测试完成! 启动线程数:9, 每线程执行测试数量: 1000, 测试数据大小(byte):1024
put处理时间:29515微秒,处理put速度: 每秒 2654 次
get处理时间:31141微秒,处理get速度: 每秒 2654 次
测试完成! 启动线程数:10, 每线程执行测试数量: 1000, 测试数据大小(byte):1024
put处理时间:37780微秒,处理put速度: 每秒 2285 次
get处理时间:42876微秒,处理get速度: 每秒 2285 次
没有测试下去了,看来8~9个线程效率最高,服务端测试的时候,CPU一直使用率很低,最多到5%.
以上测试结果最多到了2500左右,但有位朋友的测试结果非常惊人,一个线程都超过了3300和4800的处理量,他的传输数据量小点,只有0.1k,我测试了下,用这个数据量,顶多也是到3000多的并发。他的测试结果请看如下网址:
http://hi.baidu.com/jabber/blog/category/Memcached
评论
runs * threads * 1000 / time
runs * threads * 1000 / time
应该改为
runs * threads * 1000 / putTimes
runs * threads * 1000 / getTimes
iunknown 已经指出来了,不过我忘记了修改论坛内容,测试性能特别高的别太早高兴。
可以试试用这个工具来测试
http://code.google.com/p/spcached/wiki/benchmarktool
runs * threads * 1000 / time
runs * threads * 1000 / time
应该改为
runs * threads * 1000 / putTimes
runs * threads * 1000 / getTimes
iunknown 已经指出来了,不过我忘记了修改论坛内容,测试性能特别高的别太早高兴。
测试完成! 启动线程数:10, 每线程执行测试数量: 10000, 测试数据大小(byte):1000
put处理时间:327687微秒,处理put速度: 每秒 9953 次
get处理时间:120751微秒,处理get速度: 每秒 9953 次
put处理时间:23864微秒,处理put速度: 每秒 335 次
get处理时间:22403微秒,处理get速度: 每秒 357 次
put处理时间:15769微秒,处理put速度: 每秒 443 次
get处理时间:14981微秒,处理get速度: 每秒 467 次
put处理时间:17335微秒,处理put速度: 每秒 403 次
get处理时间:17664微秒,处理get速度: 每秒 396 次
put处理时间:30093微秒,处理put速度: 每秒 6351 次
get处理时间:26478微秒,处理get速度: 每秒 6351 次
居然达到 每秒 6351 次
测试完成! 启动线程数:1, 每线程执行测试数量: 1000, 测试数据大小(byte):1024
put处理时间:1010微秒,处理put速度: 每秒 1005 次
get处理时间:995微秒,处理get速度: 每秒 1005 次
测试完成! 启动线程数:1, 每线程执行测试数量: 1000, 测试数据大小(byte):1024
put处理时间:1014微秒,处理put速度: 每秒 1031 次
get处理时间:969微秒,处理get速度: 每秒 1031 次
测试完成! 启动线程数:1, 每线程执行测试数量: 1000, 测试数据大小(byte):1024
put处理时间:995微秒,处理put速度: 每秒 999 次
get处理时间:1001微秒,处理get速度: 每秒 999 次
测试完成! 启动线程数:10, 每线程执行测试数量: 1000, 测试数据大小(byte):1024
put处理时间:30951微秒,处理put速度: 每秒 2881 次
get处理时间:30531微秒,处理get速度: 每秒 2881 次
测试完成! 启动线程数:9, 每线程执行测试数量: 1000, 测试数据大小(byte):1024
put处理时间:25449微秒,处理put速度: 每秒 3119 次
get处理时间:26399微秒,处理get速度: 每秒 3119 次
3台 在加入一台 本地机器 64m
测试完成! 启动线程数:9, 每线程执行测试数量: 1000, 测试数据大小(byte):1024
put处理时间:61636微秒,处理put速度: 每秒 1466 次
get处理时间:43753微秒,处理get速度: 每秒 1466 次
哈哈,这个都让你看出来了,厉害,确实错了。我重新测试了下,结果如下:
我建议的做法也是有问题的。我认为比较合理的做法应该像这样子:
http://code.google.com/p/spcached/wiki/benchmarktool
public static void main(String[] args) throws Exception {
......
long begin = System.currentTimeMillis();
for (int i = 0; i < threads; i++) {
statArray[i] = new WorkerStat();
statArray[i].start = start + i * runs;
statArray[i].runs = runs;
threadArray[i] = new SetterThread( statArray[i] );
threadArray[i].start();
}
for( int i = 0; i < threads; i++ ) {
threadArray[i].join();
}
mainStat.setterTime = System.currentTimeMillis() - begin;
......
}
应该在主线程中 join 等待线程结束,在主线程中测量所用的时间(mainStat.setterTime)。用这个时间计算出来的 RequestPerSecond 就代表从整个程序的角度来计算的结果。而上面我提到的计算方法,计算的是每个线程的角度来计算的结果。
#
# System.out.println("put处理时间:" + putTimes
# + "微秒,处理put速度: 每秒 " + runs * threads * 1000 / time
# + " 次");
# System.out.println("get处理时间:" + getTimes
# + "微秒,处理get速度: 每秒 " + runs * threads * 1000 / time
# + " 次");
runs * threads * 1000 / time
这个怀疑是写错了吧?应该分别是
runs * threads * 1000 / putTimes
runs * threads * 1000 / getTimes
哈哈,这个都让你看出来了,厉害,确实错了。我重新测试了下,结果如下:
测试完成! 启动线程数:1, 每线程执行测试数量: 1000, 测试数据大小(byte):1024
put处理时间:2344微秒,处理put速度: 每秒 426 次
get处理时间:1187微秒,处理get速度: 每秒 842 次
测试完成! 启动线程数:2, 每线程执行测试数量: 1000, 测试数据大小(byte):1024
put处理时间:3422微秒,处理put速度: 每秒 584 次
get处理时间:2656微秒,处理get速度: 每秒 753 次
测试完成! 启动线程数:3, 每线程执行测试数量: 1000, 测试数据大小(byte):1024
put处理时间:6266微秒,处理put速度: 每秒 478 次
get处理时间:4219微秒,处理get速度: 每秒 711 次
测试完成! 启动线程数:4, 每线程执行测试数量: 1000, 测试数据大小(byte):1024
put处理时间:7078微秒,处理put速度: 每秒 565 次
get处理时间:6642微秒,处理get速度: 每秒 602 次
测试完成! 启动线程数:5, 每线程执行测试数量: 1000, 测试数据大小(byte):1024
put处理时间:10469微秒,处理put速度: 每秒 477 次
get处理时间:10234微秒,处理get速度: 每秒 488 次
测试完成! 启动线程数:6, 每线程执行测试数量: 1000, 测试数据大小(byte):1024
put处理时间:14422微秒,处理put速度: 每秒 416 次
get处理时间:14080微秒,处理get速度: 每秒 426 次
测试完成! 启动线程数:7, 每线程执行测试数量: 1000, 测试数据大小(byte):1024
put处理时间:20125微秒,处理put速度: 每秒 347 次
get处理时间:20233微秒,处理get速度: 每秒 345 次
#
# System.out.println("put处理时间:" + putTimes
# + "微秒,处理put速度: 每秒 " + runs * threads * 1000 / time
# + " 次");
# System.out.println("get处理时间:" + getTimes
# + "微秒,处理get速度: 每秒 " + runs * threads * 1000 / time
# + " 次");
runs * threads * 1000 / time
这个怀疑是写错了吧?应该分别是
runs * threads * 1000 / putTimes
runs * threads * 1000 / getTimes
线程数量则是受限于客户机,
没有测试到SERVER的性能。
线程数量则是受限于客户机,
没有测试到SERVER的性能。
- 浏览: 23594 次
- 性别:


- 详细资料
搜索本博客
最近加入圈子
最新评论
-
一个简单实际可用的CAS配 ...
证书部分太长,只能单独放置!放在一起显得文章太长了。如果用户不愿意点,那说明他对 ...
-- by eddie -
Tomcat SSL配置大全
你配置完成后,证书是可以信任的吗,你的证书如何获得的,只是用命令生成的吗
-- by wumingsx -
一个简单实际可用的CAS配 ...
这个测试我也做过,证书那个是个大问题,网上用户可不原意点那个钮啊!不知道博主怎么 ...
-- by Heraclesun -
Tomcat SSL配置大全
这句有问题, keytool -import -trustcacerts -al ...
-- by eddie -
Tomcat SSL配置大全
为什么 导入过程分2步,第一步是导出证书,第二步是导入到证书信任库,命令如下: ...
-- by boddi






评论排行榜