论坛首页 编程语言技术论坛

关于rails大容量网站部署的性能讨论

浏览 175054 次
该帖已经被评为精华帖
作者 正文
   发表时间:2006-06-23  
to pufan,charon:

被测试的可序列化的TestBean
import java.io.Serializable;

public class TestBean implements Serializable {
	
	private String name;

	private String pass;

	private int age;

	public int getAge() {
		return age;


	}

	public void setAge(int age) {
		this.age = age;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getPass() {
		return pass;
	}

	public void setPass(String pass) {
		this.pass = pass;
	}

}


测试程序,需要说明的是,为了避免启动开销和class载入和第一次执行的未优化的开销,先对Long对象和Date对象序列化之后,再对TestBean对象执行序列化
import java.io.ByteArrayOutputStream;
import java.io.ObjectOutputStream;
import java.util.Date;

public class SerializableTest {

	public static void testMethod(Object obj) throws Exception {	
		ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
		ObjectOutputStream outStream = new ObjectOutputStream(byteStream);
		outStream.writeObject(obj);
		outStream.flush();
		outStream.close();
		byteStream.close();	
	}

	public static void main(String[] args) throws Exception {
		Long obj = new Long(1l);
		testMethod(obj);
		Date date = new Date();
		testMethod(date);
		TestBean bean = new TestBean();
		bean.setName("fankai");
		bean.setPass("fankai");
		bean.setAge(30);
		long start = System.currentTimeMillis();				
		testMethod(bean);	
		long end = System.currentTimeMillis();
		System.out.println(end-start);
	}

}


测试环境:
硬件:P4 3.0GHz 超线程CPU,1G DDR Memory,160GB SATA 硬盘
软件:WindowsXP SP2,Sun JDK1.5.0_06

测试结果:

多次测试平均结果: 35ms

需要说明的是,我编写的web应用,使用Hibernate/Spring/Webwork,在不访问数据库的情况下,每个请求执行全过程(从ServletDispatcher接到请求到页面flush出去结束)仅仅只有10-15ms!

别光说不练,把测试程序在你机器上跑跑,我倒想看看你是怎么跑出来10ms的
0 请登录后投票
   发表时间:2006-06-23  
我使用mencached的java client的测试程序,向局域网内的服务器上传送对象20次,并取20次,效率都很好。传送之前也是经过序列化的。代码:
		int runs = Integer.parseInt("20");
		int start = Integer.parseInt("0");

		String[] serverlist = { "10.1.10.7:11211" };

		// initialize the pool for memcache servers
		SockIOPool pool = SockIOPool.getInstance();
		pool.setServers(serverlist);

		pool.setInitConn(20);
		pool.setMinConn(5);
		pool.setMaxConn(20);
		pool.setMaintSleep(30);

		pool.setNagle(false);
		pool.initialize();

		// get client instance
		MemCachedClient mc = new MemCachedClient();
		mc.setCompressEnable(false);

		String keyBase = "testKey";
		String object = "This is a test of an object blah blah es, serialization does not seem to slow things down so much.  The gzip compression is horrible horrible performance, so we only use it for very large objects.  I have not done any heavy benchmarking recently";

	    TestBean testBean = new TestBean();
	    testBean.setName(keyBase);
	    testBean.setPass(object);
	    testBean.setAge(2);
	 
		long begin = System.currentTimeMillis();
		for (int i = start; i < start+runs; i++) {
			mc.set(keyBase + i, testBean);
		}
		long end = System.currentTimeMillis();
		long time = end - begin;

		System.out.println(runs + " sets: " + time + "ms");

		begin = System.currentTimeMillis();
		for (int i = start; i < start+runs; i++) {
			TestBean str = (TestBean) mc.get(keyBase + i);
		}
		end = System.currentTimeMillis();
		time = end - begin;

		System.out.println(runs + " gets: " + time + "ms");
		SockIOPool.getInstance().shutDown();

结果数据:
20 sets: 47ms
20 gets: 31ms

机器配置 : CPU PM 1.86  Memory 1536K  PATA硬盘7200转
远程linux : CPU 3.0 Memory 1024K IBM PC Server
0 请登录后投票
   发表时间:2006-06-23  
按照robbin的程序,出来几次10,几次20,平均一下应该可以算15

testMethod(bean);;

修改为
for (int i = 0; i < 1000; i++);  testMethod(bean);;

后平均90

机器配置:
Intel(R) Pentium(R) M processor 1500MHz
1.50 GHz
1.00 GB RAM
软件 WindowsXP SP2,Sun JDK 1.4.2_11-b06
0 请登录后投票
   发表时间:2006-06-23  
我刚才也把Robin 的程序放在我的环境上运行了,运行多次都是15,16,也有时会显示0。
0 请登录后投票
   发表时间:2006-06-23  
稍微改一下代码
        public static void main(String[] args); throws Exception { 
        	for(int i =0;i<5;i++);{
                Long obj = new Long(1l);; 
                testMethod(obj);; 
                Date date = new Date();; 
                testMethod(date);; 
                TestBean bean = new TestBean();; 
                bean.setName("fankai");; 
                bean.setPass("fankai");; 
                bean.setAge(30);; 
                long start = System.currentTimeMillis();;                                
                testMethod(bean);;        
                long end = System.currentTimeMillis();; 
                System.out.println(end-start);; 
        	}
        } 



打出来的结果为:
16
0
0
0
0
0
0
0
0
0
0 请登录后投票
   发表时间:2006-06-23  
按照这个测试用例,在我的机器上跑了一下。大概是31ms (这个是TestBean的序列化耗时).

然后我改了一下程序,别的不变,就改一下main函数
        public static void main(String[] args); throws Exception { 
                long start = System.currentTimeMillis();;                                
                Long obj = new Long(1l);; 
                testMethod(obj);; 
                Date date = new Date();; 
                testMethod(date);; 
                TestBean bean = new TestBean();; 
                bean.setName("fankai");; 
                bean.setPass("fankai");; 
                bean.setAge(30);; 
                long start = System.currentTimeMillis();;
                for(int i=0;i<5000;i++);{
                    testMethod(bean);;        
                }
                long end = System.currentTimeMillis();; 
                System.out.println(end-start);; 
        } 

这个时候耗时是203ms.
0 请登录后投票
   发表时间:2006-06-23  
jetever,jkit,yuxie,charon 你们的测试方法是不对的

对同一个对象反复序列化,JVM会进行缓存,不管你循环20次,200次还是5000次,其实都是只序列化了一次,剩下的那只是循环本身的开销而已。如果你们真想得到最值得信赖的测试,那就应该真的去写一个web应用,用loadrunner去做压力测试,每个web页面去memcached取session,然后再对比测试web页面不访问memcached,这样才行。

真实的运行环境中,每个JVM里面的每个线程要序列化的对象都不同,我的请求线程去序列化我的user对象,你的线程去序列化你的user对象,这个时候JVM是没有办法进行缓存的,只有老老实实每次都序列化。根据我的测试,稍微复杂的对象序列化开销要达到50ms(即使TestBean也要35ms了)

我的压力测试结果表明每个HTTP请求在不访问数据库的时候只需要10ms,即使访问数据库,开销也在100ms以内(除非数据量很大)。这种情况下,一旦加上对memcache的访问,Java序列化开销就显得过于昂贵了。
0 请登录后投票
   发表时间:2006-06-23  
robbin 写道
jetever,jkit,yuxie 你们的测试是不对的

对同一个对象反复序列化,JVM会进行缓存,不管你循环20次,还是200次,其实都是只序列化了一次。

真实的运行环境中,每个JVM里面的每个线程要序列化的对象都不同,我的请求线程去序列化我的user对象,你的线程去序列化你的user对象,这个时候JVM是没有办法进行缓存的,只有老老实实每次都序列化。根据我的测试,稍微复杂的对象序列化开销要达到50ms(即使TestBean也要35ms了)

我每个HTTP请求在不访问数据库的时候只需要10ms,即使访问数据库,开销也在100ms以内(除非数据量很大)。这种情况下,Java序列化开销就显得过于昂贵了。


又换了个方式测试
                for (int i = 0; i < 10; i++);     {               
                    long start = System.currentTimeMillis();;            
                    TestBean bean = new TestBean();;
                    bean.setName("fankai" + i);;
                    bean.setPass("fankai" + i);;
                    bean.setAge(30 + i);;
                    testMethod(bean);;       
                    long end = System.currentTimeMillis();;
                    System.out.println("main:" + (end-start););;
                }

每次都重新new一个对象,并且set不同的值,结果大同小异,第一次出20,后面都是0,偶尔会蹦一两个10。
0 请登录后投票
   发表时间:2006-06-23  
我修改了程序,每次的对象都是重新负值 不知道这样还有没有缓存。但是测试的结果数据还是和最早的同样。
		for (int i = start; i < start + runs; i++); {
			TestBean testBean = new TestBean();;
			testBean.setName(keyBase + i);;
			testBean.setPass(object + i);;
			testBean.setAge(2 + i);;

			mc.set(keyBase + i, testBean);;
		}
0 请登录后投票
   发表时间:2006-06-23  
根据robbin的意见,改了程序
import java.io.ByteArrayOutputStream; 
import java.io.ObjectOutputStream; 
import java.util.Date; 

public class SerializableTest { 

        public static void testMethod(Object obj); throws Exception {        
                ByteArrayOutputStream byteStream = new ByteArrayOutputStream();; 
                ObjectOutputStream outStream = new ObjectOutputStream(byteStream);; 
                outStream.writeObject(obj);; 
                outStream.flush();; 
                outStream.close();; 
                byteStream.close();;        
        } 

        public static void main(String[] args); throws Exception { 
                Long obj = new Long(1l);; 
                testMethod(obj);; 
                Date date = new Date();; 
                testMethod(date);; 
                TestBean bean = new TestBean();; 
                bean.setName("fankai");; 
                bean.setPass("fankai");; 
                bean.setAge(30);; 
                long start = System.currentTimeMillis();;                                
                for(int i=0;i<5000;i++);{
                    testMethod2(i);;        
                }
                long end = System.currentTimeMillis();; 
                System.out.println(end-start);; 
        } 

        public static void testMethod2(int i); throws Exception {        
                TestBean bean = new TestBean();; 
                bean.setName("fankai");; 
                bean.setPass("fankai");; 
                bean.setAge(i);; 
                ByteArrayOutputStream byteStream = new ByteArrayOutputStream();; 
                ObjectOutputStream outStream = new ObjectOutputStream(byteStream);; 
                outStream.writeObject(bean);; 
                outStream.flush();; 
                outStream.close();; 
                byteStream.close();;        
        } 
}


结果当i=1的时候还是 31ms
i=5000的时候也仍然是203ms
0 请登录后投票
论坛首页 编程语言技术版

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