论坛首页 Java企业应用论坛

MemCached 压力测试

浏览 17986 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2007-05-07  

MemCached安装完成后,进行了压力测试,主要参考了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

测试代码:

 

java 代码
  1. import com.danga.MemCached.MemCachedClient;   
  2. import com.danga.MemCached.SockIOPool;   
  3.   
  4. public class TestMemCache {   
  5.     static SockIOPool pool;   
  6.   
  7.     static int threads; // 运行的测试线程数   
  8.   
  9.     static int runs; // 每个线程运行的次数   
  10.   
  11.     static int size; // 设置到memcache中的数据包大小,单位k   
  12.   
  13.     static Integer myLock;// 锁定以下计数器   
  14.   
  15.     static long putTimes = 0// put总时间,单位微秒   
  16.   
  17.     static long getTimes = 0// get总时间,单位微秒   
  18.   
  19.     /**  
  20.      * @param args  
  21.      */  
  22.     public static void main(String[] args) {   
  23.         String[] serverlist = { "192.168.0.56:11211""192.168.0.56:11212" };   
  24.   
  25.         // initialize the pool for memcache servers   
  26.         pool = SockIOPool.getInstance();   
  27.         pool.setServers(serverlist);   
  28.   
  29.         pool.setInitConn(5);   
  30.         pool.setMinConn(5);   
  31.         pool.setMaxConn(50);   
  32.         pool.setMaintSleep(30);   
  33.   
  34.         pool.setNagle(false);   
  35.         pool.initialize();   
  36.   
  37.         if (args.length < 3) {   
  38.             System.out.println("用法:TestMemCache 启动线程数 每线程执行测试数量 测试数据大小(k)");   
  39.             System.exit(1);   
  40.         }   
  41.   
  42.         threads = Integer.parseInt(args[0]);   
  43.         runs = Integer.parseInt(args[1]);   
  44.         size = 100 * Integer.parseInt(args[2]);   
  45.   
  46.         myLock = new Integer(threads);   
  47.   
  48.         for (int i = 0; i < threads; i++) {   
  49.             Thread thread = new WorkerThread();   
  50.             thread.start();   
  51.         }   
  52.     }   
  53.   
  54.     private static class WorkerThread extends Thread {   
  55.   
  56.         // 构造函数   
  57.         WorkerThread() {   
  58.         }   
  59.   
  60.         public void run() {   
  61.             // get client instance   
  62.             MemCachedClient mc = new MemCachedClient();   
  63.   
  64.             mc.setCompressEnable(false);   
  65.             mc.setCompressThreshold(0);   
  66.   
  67.             // get object to store   
  68.             int[] obj = new int[size];   
  69.             for (int i = 0; i < size; i++) {   
  70.                 obj[i] = i;   
  71.             }   
  72.   
  73.             String[] keys = new String[runs];   
  74.             for (int i = 0; i < runs; i++) {   
  75.                 keys[i] = "test_key" + i;   
  76.             }   
  77.   
  78.             for (int i = 0; i < runs; i++) {   
  79.                 mc.delete(keys[i]);   
  80.             }   
  81.   
  82.             long startTime = System.currentTimeMillis();   
  83.             for (int i = 0; i < runs; i++) {   
  84.                 mc.set(keys[i], obj);   
  85.             }   
  86.             long time = System.currentTimeMillis() - startTime;   
  87.   
  88.             synchronized (myLock) {   
  89.                 putTimes += time;   
  90.             }   
  91.   
  92.             startTime = System.currentTimeMillis();   
  93.             for (int i = 0; i < runs; i++) {   
  94.                 mc.get(keys[i]);   
  95.             }   
  96.             time = System.currentTimeMillis() - startTime;   
  97.   
  98.             synchronized (myLock) {   
  99.                 getTimes += time;   
  100.                 myLock--;   
  101.   
  102.                 if (myLock.equals(0)) {   
  103.                     System.out.println("测试完成! 启动线程数:" + threads   
  104.                             + ", 每线程执行测试数量: " + runs + ", 测试数据大小(byte):" + size);   
  105.   
  106.                     System.out.println("put处理时间:" + putTimes   
  107.                             + "微秒,处理put速度: 每秒 " + runs * threads * 1000 / putTimes   
  108.                             + " 次");   
  109.                     System.out.println("get处理时间:" + getTimes   
  110.                             + "微秒,处理get速度: 每秒 " + runs * threads * 1000 / getTimes   
  111.                             + " 次");   
  112.   
  113.                     pool.shutDown();   
  114.                 }   
  115.             }   
  116.         }   
  117.     }   
  118.   
  119. }   

 测试结果:

测试完成! 启动线程数: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

 

   发表时间:2007-05-07  
我认为你这个测试,数据处理速度应当是受限于网络,
线程数量则是受限于客户机,
没有测试到SERVER的性能。
0 请登录后投票
   发表时间:2007-05-08  
rtdb 写道
我认为你这个测试,数据处理速度应当是受限于网络,
线程数量则是受限于客户机,
没有测试到SERVER的性能。
我们的局域网就这速度,没办法。客户端应该没啥限制的,我的客户机是个IBM笔记本,配置还可以,1.5G内存,双核CPU。
0 请登录后投票
   发表时间:2007-05-17  
引用

#
#                     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
0 请登录后投票
   发表时间:2007-05-17  
iunknown 写道
引用

#
#                     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 次
0 请登录后投票
   发表时间:2007-05-18  
eddie 写道

哈哈,这个都让你看出来了,厉害,确实错了。我重新测试了下,结果如下:


我建议的做法也是有问题的。我认为比较合理的做法应该像这样子:
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 就代表从整个程序的角度来计算的结果。而上面我提到的计算方法,计算的是每个线程的角度来计算的结果。
0 请登录后投票
   发表时间:2007-07-27  
2台  1台 2g  一台 64m
测试完成! 启动线程数: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 次
0 请登录后投票
   发表时间:2007-07-27  
3台 在加入一台 本地机器 64m 性能为何变差 ???
0 请登录后投票
   发表时间:2007-07-27  
测试完成! 启动线程数:9, 每线程执行测试数量: 1000, 测试数据大小(byte):1024
put处理时间:30093微秒,处理put速度: 每秒 6351 次
get处理时间:26478微秒,处理get速度: 每秒 6351 次

居然达到 每秒 6351 次
0 请登录后投票
   发表时间:2007-07-27  
测试完成! 启动线程数:7, 每线程执行测试数量: 1000, 测试数据大小(byte):1024
put处理时间:17335微秒,处理put速度: 每秒 403 次
get处理时间:17664微秒,处理get速度: 每秒 396 次
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics