<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Tim[后端技术] &#187; Java</title>
	<atom:link href="http://timyang.net/tag/java/feed/" rel="self" type="application/rss+xml" />
	<link>http://timyang.net</link>
	<description>Tim&#039;s blog, 关于后端架构、互联网技术、分布式、大型网络应用、NoSQL、Key Value等</description>
	<lastBuildDate>Mon, 26 Jul 2010 15:32:05 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.1</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>C, Erlang, Java and Go Web Server performance test</title>
		<link>http://timyang.net/programming/c-erlang-java-performance/</link>
		<comments>http://timyang.net/programming/c-erlang-java-performance/#comments</comments>
		<pubDate>Wed, 11 Nov 2009 13:28:18 +0000</pubDate>
		<dc:creator>Tim</dc:creator>
				<category><![CDATA[编程]]></category>
		<category><![CDATA[English]]></category>
		<category><![CDATA[Erlang]]></category>
		<category><![CDATA[Go]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[nginx]]></category>
		<category><![CDATA[web server]]></category>

		<guid isPermaLink="false">http://timyang.net/?p=468</guid>
		<description><![CDATA[I had tested a hello world web server in C, Erlang, Java and the Go programming language.
* C, use the well-known high performance web server nginx, with a hello world nginx module
* Erlang/OTP
* Java, using the MINA 2.0 framework, now the JBoss Netty framework.
* Go, http://golang.org/
1. Test environment
1.1 Hardware/OS
2 Linux boxes in a gigabit ethernet [...]]]></description>
			<content:encoded><![CDATA[<p>I had tested a hello world web server in C, Erlang, Java and the Go programming language.<br />
* C, use the well-known high performance web server nginx, with a hello world nginx module<br />
* Erlang/OTP<br />
* Java, using <span style="text-decoration: line-through;">the MINA 2.0 framework</span>, now the JBoss <a href="http://www.jboss.org/netty/">Netty</a> framework.<br />
* Go, <a href="http://golang.org/">http://golang.org/</a></p>
<h3>1. Test environment</h3>
<h4>1.1 Hardware/OS</h4>
<p>2 Linux boxes in a gigabit ethernet LAN, 1 server and 1 test client<br />
Linux Centos 5.2 64bit<br />
Intel(R) Xeon(R) CPU E5410  @ 2.33GHz (L2 cache: 6M), Quad-Core * 2<br />
8G memory<br />
SCSI disk (standalone disk, no other access)</p>
<h4>1.2 Software version</h4>
<p>nginx, nginx-0.7.63.tar.gz<br />
Erlang, otp_src_R13B02-1.tar.gz<br />
Java, jdk-6u17-linux-x64.bin, mina-2.0.0-RC1.tar.gz, netty-3.2.0.ALPHA1-dist.tar.bz2<br />
Go, hg clone -r release <a href="https://go.googlecode.com/hg/">https://go.googlecode.com/hg/</a> $GOROOT (Nov 12, 2009)</p>
<h4>1.3 Source code and configuration</h4>
<p><strong>Linux</strong>, run sysctl -p</p>
<pre>net.ipv4.ip_forward = 0
net.ipv4.conf.default.rp_filter = 1
net.ipv4.conf.default.accept_source_route = 0
kernel.sysrq = 0
kernel.core_uses_pid = 1
net.ipv4.tcp_syncookies = 1
kernel.msgmnb = 65536
kernel.msgmax = 65536
kernel.shmmax = 68719476736
kernel.shmall = 4294967296
kernel.panic = 1
net.ipv4.tcp_rmem = 8192	873800	8738000
net.ipv4.tcp_wmem = 4096	655360	6553600
net.ipv4.ip_local_port_range = 1024	65000
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216</pre>
<p># ulimit -n<br />
150000</p>
<p><strong>C</strong>: ngnix hello world module, copy the code ngx_http_hello_module.c from <a href="http://timyang.net/web/nginx-module/">http://timyang.net/web/nginx-module/</a></p>
<p>in nginx.conf, set &#8220;worker_processes  1; worker_connections 10240&#8243; for 1 cpu test, set &#8220;worker_processes  4; worker_connections 2048&#8243; for multi-core cpu test. Turn off all access or debug log in nginx.conf, as follows</p>
<pre>worker_processes  1;
worker_rlimit_nofile 10240;
events {
    worker_connections  10240;
}
http {
    include       mime.types;
    default_type  application/octet-stream;
    sendfile        on;
    keepalive_timeout  0;
    server {
        listen       8080;
        server_name  localhost;
        location / {
            root   html;
            index  index.html index.htm;
        }
          location /hello {
            ngx_hello_module;
            hello 1234;
        }

        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }
    }
}</pre>
<p>$ taskset -c 1 ./nginx or $ taskset -c 1-7 ./nginx</p>
<p><strong>Erlang</strong> hello world server<br />
The source code is available at yufeng&#8217;s blog, see <a href="http://blog.yufeng.info/archives/105">http://blog.yufeng.info/archives/105</a><br />
Just copy the code after &#8220;cat ehttpd.erl&#8221;, and compile it.</p>
<p>$ erlc ehttpd.erl<br />
$ taskset -c 1 erl +K true +h 99999 +P 99999 -smp enable +S 2:1 -s ehttpd<br />
$ taskset -c 1-7 erl +K true -s ehttpd<br />
We use taskset to limit erlang vm to use only 1 CPU/core or use all CPU cores. The 2nd line is run in single CPU mode, and the 3rd line is run in multi-core CPU mode.</p>
<p><strong>Java</strong> source code, save the 2 class as HttpServer.java and HttpProtocolHandler.java, and do necessary import.<strong><br />
</strong></p>
<pre>public class HttpServer {
    public static void main(String[] args) throws Exception {
        SocketAcceptor acceptor = new NioSocketAcceptor(4);
        acceptor.setReuseAddress( true );

		int port = 8080;
		String hostname = null;
		if (args.length &gt; 1) {
			hostname = args[0];
			port = Integer.parseInt(args[1]);
		}

        // Bind
        acceptor.setHandler(new HttpProtocolHandler());
        if (hostname != null)
        	acceptor.bind(new InetSocketAddress(hostname, port));
        else
        	acceptor.bind(new InetSocketAddress(port));

        System.out.println("Listening on port " + port);
        Thread.currentThread().join();
    }
}

public class HttpProtocolHandler extends IoHandlerAdapter {
    public void sessionCreated(IoSession session) {
        session.getConfig().setIdleTime(IdleStatus.BOTH_IDLE, 10);
        session.setAttribute(SslFilter.USE_NOTIFICATION);
    }

    public void sessionClosed(IoSession session) throws Exception {}
    public void sessionOpened(IoSession session) throws Exception {}
    public void sessionIdle(IoSession session, IdleStatus status) {}
    public void exceptionCaught(IoSession session, Throwable cause) {
        session.close(true);
    }

    static IoBuffer RESULT = null;
	public static String HTTP_200 = "HTTP/1.1 200 OK\r\nContent-Length: 13\r\n\r\n" +
			"hello world\r\n";
	static {
    	RESULT = IoBuffer.allocate(32).setAutoExpand(true);
    	RESULT.put(HTTP_200.getBytes());
    	RESULT.flip();
    }
    public void messageReceived(IoSession session, Object message)
            throws Exception {
        if (message instanceof IoBuffer) {
        	IoBuffer buf = (IoBuffer) message;
        	int c = buf.get();
        	if (c == 'G' || c == 'g') {
        		session.write(RESULT.duplicate());
        	}
        	session.close(false);
        }
    }
}</pre>
<p><strong>Nov 24 update</strong> Because the above Mina code doesn&#8217;t parse HTTP request and handle the necessary HTTP protocol, replaced with org.jboss.netty.example.http.snoop.HttpServer from Netty example, but removed all the string builder code from HttpRequestHandler.messageReceived() and just return a &#8220;hello world&#8221; result in HttpRequestHandler.writeResponse(). Please read the <a href="http://www.jboss.org/file-access/default/members/netty/freezone/xref/3.2/org/jboss/netty/example/http/snoop/package-summary.html">source code</a> and the <a href="http://www.jboss.org/netty/documentation.html">Netty documentation</a> for more information.</p>
<p>$ taskset -c 1-7 \<br />
java -server -Xmx1024m -Xms1024m -XX:+UseConcMarkSweepGC -classpath . test.HttpServer 192.168.10.1 8080</p>
<p>We use taskset to limit java only use cpu1-7, and not use cpu0, because we want cpu0 dedicate for system call(Linux use CPU0 for network interruptions).</p>
<p>Go language, source code</p>
<pre>package main
import (
   "http";
    "io";
)
func HelloServer(c *http.Conn, req *http.Request) {
    io.WriteString(c, "hello, world!\n");
}
func main() {
     runtime.GOMAXPROCS(8); // 8 cores
     http.Handle("/", http.HandlerFunc(HelloServer));
     err := http.ListenAndServe(":8080", nil);
    if err != nil {
        panic("ListenAndServe: ", err.String())
    }
}</pre>
<p>$ 6g httpd2.go<br />
$ 6l httpd2.6<br />
$ taskset -c 1-7 ./6.out</p>
<h4>1.4 Performance test client</h4>
<p>ApacheBench client, for 30, 100, 1,000, 5,000 concurrent threads<br />
ab -c 30 -n 1000000 <a href="http://192.168.10.1:8080/">http://192.168.10.1:8080/</a><br />
ab -c 100 -n 1000000 <a href="http://192.168.10.1:8080/">http://192.168.10.1:8080/</a><br />
1000 thread, 334 from 3 different machine<br />
ab -c 334 -n 334000 <a href="http://192.168.10.1:8080/">http://192.168.10.1:8080/</a><br />
5000 thread, 1667 from 3 different machine<br />
ab -c 1667 -n 334000 <a href="http://192.168.10.1:8080/">http://192.168.10.1:8080/</a></p>
<h3>2. Test results</h3>
<h4>2.1 request per second</h4>
<table style="width: 437pt; border-collapse: collapse;" border="0" cellspacing="0" cellpadding="0" width="580">
<colgroup span="1">
<col style="width: 167pt;" span="1" width="222"></col>
<col style="width: 91pt;" span="1" width="121"></col>
<col style="width: 61pt;" span="1" width="81"></col>
<col style="width: 65pt;" span="1" width="86"></col>
<col style="width: 53pt;" span="1" width="70"></col>
</colgroup>
<tbody>
<tr style="height: 15pt;" height="20">
<td class="xl24" style="border: medium none #d4d0c8; width: 167pt; height: 15pt; background-color: transparent;" width="222" height="20"></td>
<td class="xl26" style="border: medium none #d4d0c8; width: 91pt; background-color: transparent;" width="121"><span style="font-size: small;">30 (threads)</span></td>
<td class="xl24" style="border: medium none #d4d0c8; width: 61pt; background-color: transparent;" width="81" align="right"><span style="font-size: small;">100</span></td>
<td class="xl24" style="border: medium none #d4d0c8; width: 65pt; background-color: transparent;" width="86" align="right"><span style="font-size: small;">1,000</span></td>
<td class="xl25" style="border: medium none #d4d0c8; width: 53pt; background-color: transparent;" width="70" align="right"><span style="font-size: small;">5,000</span></td>
</tr>
<tr style="height: 15pt;" height="20">
<td class="xl24" style="border: medium none #d4d0c8; width: 167pt; height: 15pt; background-color: transparent;" width="222" height="20"><span style="font-size: small;">Nginx html(1C)</span></td>
<td class="xl27" style="border: medium none #d4d0c8; width: 91pt; background-color: transparent;" width="121" align="right"><span style="font-size: small;">21,301 </span></td>
<td class="xl27" style="border: medium none #d4d0c8; width: 61pt; background-color: transparent;" width="81" align="right"><span style="font-size: small;">21,331 </span></td>
<td class="xl27" style="border: medium none #d4d0c8; width: 65pt; background-color: transparent;" width="86" align="right"><span style="font-size: small;">23,746 </span></td>
<td class="xl28" style="background-color: transparent; border: #d4d0c8;" align="right"><span style="font-size: small;">23,502 </span></td>
</tr>
<tr style="height: 15pt;" height="20">
<td class="xl24" style="border: medium none #d4d0c8; width: 167pt; height: 15pt; background-color: transparent;" width="222" height="20"><span style="font-size: small;">Nginx module(1C)</span></td>
<td class="xl27" style="border: medium none #d4d0c8; width: 91pt; background-color: transparent;" width="121" align="right"><span style="font-size: small;">25,809 </span></td>
<td class="xl27" style="border: medium none #d4d0c8; width: 61pt; background-color: transparent;" width="81" align="right"><span style="font-size: small;">25,735 </span></td>
<td class="xl27" style="border: medium none #d4d0c8; width: 65pt; background-color: transparent;" width="86" align="right"><span style="font-size: small;">30,380 </span></td>
<td class="xl28" style="background-color: transparent; border: #d4d0c8;" align="right"><span style="font-size: small;">29,667</span></td>
</tr>
<tr style="height: 15pt;" height="20">
<td class="xl24" style="border: medium none #d4d0c8; width: 167pt; height: 15pt; background-color: transparent;" width="222" height="20"><span style="font-size: small;">Nginx module(Multi-core)</span></td>
<td class="xl27" style="border: medium none #d4d0c8; width: 91pt; background-color: transparent;" width="121" align="right"><span style="font-size: small;">25,057 </span></td>
<td class="xl27" style="border: medium none #d4d0c8; width: 61pt; background-color: transparent;" width="81" align="right"><span style="font-size: small;">24,507 </span></td>
<td class="xl27" style="border: medium none #d4d0c8; width: 65pt; background-color: transparent;" width="86" align="right"><span style="font-size: small;">31,544 </span></td>
<td class="xl28" style="background-color: transparent; border: #d4d0c8;" align="right"><span style="font-size: small;">33,274 </span></td>
</tr>
<tr style="height: 15pt;" height="20">
<td class="xl24" style="border: medium none #d4d0c8; width: 167pt; height: 15pt; background-color: transparent;" width="222" height="20"><span style="font-size: small;">Erlang(1C)</span></td>
<td class="xl27" style="border: medium none #d4d0c8; width: 91pt; background-color: transparent;" width="121" align="right"><span style="font-size: small;">11,585 </span></td>
<td class="xl27" style="border: medium none #d4d0c8; width: 61pt; background-color: transparent;" width="81" align="right"><span style="font-size: small;">12,367 </span></td>
<td class="xl27" style="border: medium none #d4d0c8; width: 65pt; background-color: transparent;" width="86" align="right"><span style="font-size: small;">12,852 </span></td>
<td class="xl28" style="background-color: transparent; border: #d4d0c8;" align="right"><span style="font-size: small;">12,815 </span></td>
</tr>
<tr style="height: 15pt;" height="20">
<td class="xl24" style="border: medium none #d4d0c8; width: 167pt; height: 15pt; background-color: transparent;" width="222" height="20"><span style="font-size: small;">Erlang(Multi-Core)</span></td>
<td class="xl27" style="border: medium none #d4d0c8; width: 91pt; background-color: transparent;" width="121" align="right"><span style="font-size: small;">15,101 </span></td>
<td class="xl27" style="border: medium none #d4d0c8; width: 61pt; background-color: transparent;" width="81" align="right"><span style="font-size: small;">20,255 </span></td>
<td class="xl27" style="border: medium none #d4d0c8; width: 65pt; background-color: transparent;" width="86" align="right"><span style="font-size: small;">26,468 </span></td>
<td class="xl28" style="background-color: transparent; border: #d4d0c8;" align="right"><span style="font-size: small;">25,865 </span></td>
</tr>
<tr style="height: 15pt;" height="20">
<td class="xl24" style="border: medium none #d4d0c8; width: 167pt; height: 15pt; background-color: transparent;" width="222" height="20"><span style="text-decoration: line-through;"><span style="font-size: small;">Java, Mina2(without HTTP parse)<br />
</span></span></td>
<td class="xl27" style="border: medium none #d4d0c8; width: 91pt; background-color: transparent;" width="121" align="right"><span style="font-size: small;"><span style="text-decoration: line-through;">30,631</span> </span></td>
<td class="xl27" style="border: medium none #d4d0c8; width: 61pt; background-color: transparent;" width="81" align="right"><span style="font-size: small;"><span style="text-decoration: line-through;">26,846</span> </span></td>
<td class="xl27" style="border: medium none #d4d0c8; width: 65pt; background-color: transparent;" width="86" align="right"><span style="font-size: small;"><span style="text-decoration: line-through;">31,911</span> </span></td>
<td class="xl28" style="background-color: transparent; border: #d4d0c8;" align="right"><span style="font-size: small;"><span style="text-decoration: line-through;">31,653</span> </span></td>
</tr>
<tr style="height: 15pt;" height="20">
<td class="xl24" style="border: medium none #d4d0c8; width: 167pt; height: 15pt; background-color: transparent;" width="222" height="20"><span style="font-size: small;">Java, Netty</span></td>
<td class="xl27" style="border: medium none #d4d0c8; width: 91pt; background-color: transparent;" width="121" align="right"><span style="font-size: small;">24,152 </span></td>
<td class="xl27" style="border: medium none #d4d0c8; width: 61pt; background-color: transparent;" width="81" align="right"><span style="font-size: small;">24,423 </span></td>
<td class="xl27" style="border: medium none #d4d0c8; width: 65pt; background-color: transparent;" width="86" align="right"><span style="font-size: small;">25,487 </span></td>
<td class="xl28" style="background-color: transparent; border: #d4d0c8;" align="right"><span style="font-size: small;">25,521 </span></td>
</tr>
<tr style="height: 15pt;" height="20">
<td class="xl24" style="border: medium none #d4d0c8; width: 167pt; height: 15pt; background-color: transparent;" width="222" height="20"><span style="font-size: small;">Go</span></td>
<td class="xl27" style="border: medium none #d4d0c8; width: 91pt; background-color: transparent;" width="121" align="right"><span style="font-size: small;">14,080 </span></td>
<td class="xl27" style="border: medium none #d4d0c8; width: 61pt; background-color: transparent;" width="81" align="right"><span style="font-size: small;">14,748 </span></td>
<td class="xl27" style="border: medium none #d4d0c8; width: 65pt; background-color: transparent;" width="86" align="right"><span style="font-size: small;">15,799 </span></td>
<td class="xl27" style="border: medium none #d4d0c8; width: 53pt; background-color: transparent;" width="70" align="right"><span style="font-size: small;">16,110 </span></td>
</tr>
</tbody>
</table>
<h4><img class="alignnone size-full wp-image-505" title="c_erlang_java_go" src="http://timyang.net/blog/wp-content/uploads/2009/11/c_erlang_java_go.png" alt="c_erlang_java_go" width="612" height="369" /><br />
2.2 latency, 99% requests within(ms)</h4>
<table style="width: 437pt; border-collapse: collapse;" border="0" cellspacing="0" cellpadding="0" width="580">
<colgroup span="1">
<col style="width: 167pt;" span="1" width="222"></col>
<col style="width: 91pt;" span="1" width="121"></col>
<col style="width: 61pt;" span="1" width="81"></col>
<col style="width: 65pt;" span="1" width="86"></col>
<col style="width: 53pt;" span="1" width="70"></col>
</colgroup>
<tbody>
<tr style="height: 15pt;" height="20">
<td class="xl24" style="border: medium none #d4d0c8; width: 167pt; height: 15pt; background-color: transparent;" width="222" height="20"></td>
<td class="xl25" style="border: medium none #d4d0c8; width: 91pt; background-color: transparent;" width="121" align="right"><span style="font-size: small;">30 </span></td>
<td class="xl25" style="border: medium none #d4d0c8; width: 61pt; background-color: transparent;" width="81" align="right"><span style="font-size: small;">100 </span></td>
<td class="xl25" style="border: medium none #d4d0c8; width: 65pt; background-color: transparent;" width="86" align="right"><span style="font-size: small;">1,000 </span></td>
<td class="xl25" style="border: medium none #d4d0c8; width: 53pt; background-color: transparent;" width="70" align="right"><span style="font-size: small;">5,000 </span></td>
</tr>
<tr style="height: 15pt;" height="20">
<td class="xl24" style="border: medium none #d4d0c8; width: 167pt; height: 15pt; background-color: transparent;" width="222" height="20"><span style="font-size: small;">Nginx html(1C)</span></td>
<td class="xl25" style="border: medium none #d4d0c8; width: 91pt; background-color: transparent;" width="121" align="right"><span style="font-size: small;">1 </span></td>
<td class="xl25" style="border: medium none #d4d0c8; width: 61pt; background-color: transparent;" width="81" align="right"><span style="font-size: small;">4 </span></td>
<td class="xl25" style="border: medium none #d4d0c8; width: 65pt; background-color: transparent;" width="86" align="right"><span style="font-size: small;">42 </span></td>
<td class="xl25" style="border: medium none #d4d0c8; width: 53pt; background-color: transparent;" width="70" align="right"><span style="font-size: small;">3,079 </span></td>
</tr>
<tr style="height: 15pt;" height="20">
<td class="xl24" style="border: medium none #d4d0c8; width: 167pt; height: 15pt; background-color: transparent;" width="222" height="20"><span style="font-size: small;">Nginx module(1C)</span></td>
<td class="xl25" style="border: medium none #d4d0c8; width: 91pt; background-color: transparent;" width="121" align="right"><span style="font-size: small;">1 </span></td>
<td class="xl25" style="border: medium none #d4d0c8; width: 61pt; background-color: transparent;" width="81" align="right"><span style="font-size: small;">4 </span></td>
<td class="xl25" style="border: medium none #d4d0c8; width: 65pt; background-color: transparent;" width="86" align="right"><span style="font-size: small;">32 </span></td>
<td class="xl25" style="border: medium none #d4d0c8; width: 53pt; background-color: transparent;" width="70" align="right"><span style="font-size: small;">3,047 </span></td>
</tr>
<tr style="height: 15pt;" height="20">
<td class="xl24" style="border: medium none #d4d0c8; width: 167pt; height: 15pt; background-color: transparent;" width="222" height="20"><span style="font-size: small;">Nginx module(Multi-core)</span></td>
<td class="xl25" style="border: medium none #d4d0c8; width: 91pt; background-color: transparent;" width="121" align="right"><span style="font-size: small;">1 </span></td>
<td class="xl25" style="border: medium none #d4d0c8; width: 61pt; background-color: transparent;" width="81" align="right"><span style="font-size: small;">6 </span></td>
<td class="xl25" style="border: medium none #d4d0c8; width: 65pt; background-color: transparent;" width="86" align="right"><span style="font-size: small;">205 </span></td>
<td class="xl25" style="border: medium none #d4d0c8; width: 53pt; background-color: transparent;" width="70" align="right"><span style="font-size: small;">3,036 </span></td>
</tr>
<tr style="height: 15pt;" height="20">
<td class="xl24" style="border: medium none #d4d0c8; width: 167pt; height: 15pt; background-color: transparent;" width="222" height="20"><span style="font-size: small;">Erlang(1C)</span></td>
<td class="xl25" style="border: medium none #d4d0c8; width: 91pt; background-color: transparent;" width="121" align="right"><span style="font-size: small;">3 </span></td>
<td class="xl25" style="border: medium none #d4d0c8; width: 61pt; background-color: transparent;" width="81" align="right"><span style="font-size: small;">8 </span></td>
<td class="xl25" style="border: medium none #d4d0c8; width: 65pt; background-color: transparent;" width="86" align="right"><span style="font-size: small;">629 </span></td>
<td class="xl25" style="border: medium none #d4d0c8; width: 53pt; background-color: transparent;" width="70" align="right"><span style="font-size: small;">6,337 </span></td>
</tr>
<tr style="height: 15pt;" height="20">
<td class="xl24" style="border: medium none #d4d0c8; width: 167pt; height: 15pt; background-color: transparent;" width="222" height="20"><span style="font-size: small;">Erlang(Multi-Core)</span></td>
<td class="xl25" style="border: medium none #d4d0c8; width: 91pt; background-color: transparent;" width="121" align="right"><span style="font-size: small;">2 </span></td>
<td class="xl25" style="border: medium none #d4d0c8; width: 61pt; background-color: transparent;" width="81" align="right"><span style="font-size: small;">7 </span></td>
<td class="xl25" style="border: medium none #d4d0c8; width: 65pt; background-color: transparent;" width="86" align="right"><span style="font-size: small;">223 </span></td>
<td class="xl25" style="border: medium none #d4d0c8; width: 53pt; background-color: transparent;" width="70" align="right"><span style="font-size: small;">3,084 </span></td>
</tr>
<tr style="height: 15pt;" height="20">
<td class="xl24" style="border: medium none #d4d0c8; width: 167pt; height: 15pt; background-color: transparent;" width="222" height="20"><span style="font-size: small;">Java, Netty</span></td>
<td class="xl25" style="border: medium none #d4d0c8; width: 91pt; background-color: transparent;" width="121" align="right"><span style="font-size: small;">1 </span></td>
<td class="xl25" style="border: medium none #d4d0c8; width: 61pt; background-color: transparent;" width="81" align="right"><span style="font-size: small;">3</span></td>
<td class="xl25" style="border: medium none #d4d0c8; width: 65pt; background-color: transparent;" width="86" align="right"><span style="font-size: small;">3 </span></td>
<td class="xl25" style="border: medium none #d4d0c8; width: 53pt; background-color: transparent;" width="70" align="right"><span style="font-size: small;">3,084 </span></td>
</tr>
<tr style="height: 15pt;" height="20">
<td class="xl24" style="border: medium none #d4d0c8; width: 167pt; height: 15pt; background-color: transparent;" width="222" height="20"><span style="font-size: small;">Go</span></td>
<td class="xl25" style="border: medium none #d4d0c8; width: 91pt; background-color: transparent;" width="121" align="right"><span style="font-size: small;">26</span></td>
<td class="xl25" style="border: medium none #d4d0c8; width: 61pt; background-color: transparent;" width="81" align="right"><span style="font-size: small;">33</span></td>
<td class="xl25" style="border: medium none #d4d0c8; width: 65pt; background-color: transparent;" width="86" align="right"><span style="font-size: small;">47</span></td>
<td class="xl25" style="border: medium none #d4d0c8; width: 53pt; background-color: transparent;" width="70" align="right"><span style="font-size: small;">9,005 </span></td>
</tr>
</tbody>
</table>
<h3>3. Notes</h3>
<p>* On large concurrent connections, C, Erlang, Java no big difference on their performance, results are very close.<br />
* <span style="text-decoration: line-through;">Java runs better on small connections, but the code in this test doesn&#8217;t parse the HTTP request header (the MINA code).</span><br />
* Although Mr. Yu Feng (the Erlang guru in China) mentioned that Erlang performance better on single CPU(prevent context switch), but the result tells that Erlang has big latency(&gt; 1S) under 1,000 or 5,000 connections.<br />
* <span style="text-decoration: line-through;">Go language is very close to Erlang, but still not good under heavy load (5,000 threads)</span><br />
<strong>After redo 1,000 and 5,000 tests on Nov 18</strong><br />
* Nginx module is the winner on 5,000 concurrent requests.<br />
* Although there is improvement space for Go, Go has the same performance from 30-5,000 threads.<br />
* Erlang process is impressive on large concurrent request, still as good as nginx (5,000 threads).</p>
<h3>4. Update Log</h3>
<p>Nov 12, change nginx.conf work_connections from 1024 to 10240<br />
Nov 13, add runtime.GOMAXPROCS(8); to go&#8217;s code, add sysctl -p env<br />
Nov 18, realized that <strong>ApacheBench itself is a bottleneck</strong> under 1,000 or 5,000 threads, so use 3 clients from 3 different machines to redo all tests of 1,000 and 5,000 concurrent tests.<br />
Nov 24, use Netty with full HTTP implementation to replace Mina 2 for the Java web server. Still very fast and low latency after added HTTP handle code.</p>
Similar Posts:<ul><li><a href="http://timyang.net/web/nginx-module/" rel="bookmark" title="March 17, 2009">如何写nginx module</a></li>

<li><a href="http://timyang.net/data/mcdb-tt-redis/" rel="bookmark" title="August 11, 2009">MemcacheDB, Tokyo Tyrant, Redis performance test</a></li>

<li><a href="http://timyang.net/programming/thrift-protocol-buffers-java-howto/" rel="bookmark" title="April 2, 2009">Thrift, Protocol Buffers installation and Java code howto</a></li>

<li><a href="http://timyang.net/programming/thrift-protocol-buffers-performance-java/" rel="bookmark" title="April 2, 2009">Thrift and Protocol Buffers performance in Java</a></li>

<li><a href="http://timyang.net/programming/thrift-protocol-buffers-performance-2/" rel="bookmark" title="April 17, 2009">Thrift and Protocol Buffers performance in Java Round 2</a></li>
</ul><!-- Similar Posts took 9.260 ms -->]]></content:encoded>
			<wfw:commentRss>http://timyang.net/programming/c-erlang-java-performance/feed/</wfw:commentRss>
		<slash:comments>64</slash:comments>
		</item>
		<item>
		<title>使用脚本引擎增加程序运行时动态执行能力(Java篇)</title>
		<link>http://timyang.net/java/java-scripting/</link>
		<comments>http://timyang.net/java/java-scripting/#comments</comments>
		<pubDate>Mon, 18 May 2009 11:30:33 +0000</pubDate>
		<dc:creator>Tim</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[scripting]]></category>

		<guid isPermaLink="false">http://timyang.net/?p=174</guid>
		<description><![CDATA[对于非Web的后台服务程序，经常会碰到这样的需求：

动态改变程序运行时参数的能力。如Config.limitValue = 50
动态查看运行时候变量状态的能力，如 print(userMap.size())
执行代码的能力，如 userMap.clear()

对于需求1,非Web的程序没法像PHP/JSP那样直接改就生效，往往改了某个值，即使是一个配置参数都需要服务器重启一下。这对于很多线上服务来说成本太高。
对于上述2的需求，通常是编写庞大的后台管理程序来满足。或者是通过增加日志输出，但问题是某些变量只需要偶尔才看一下，因此很多系统中大部分日志开销基本上是无用的。
对于需求3,只有通过在IDE的debug模式下才能达到。
我觉得所有的后台程序都应该具备这样的能力，为了满足以上需求，于是考虑在所有程序里面嵌入一个小型的解释脚本引擎来实现。就像很多游戏程序嵌入Lua/Python来动态执行代码目的一样。
今天先说下Java中的实现方法，几年前用过BeanShell, 可以在Java VM里面解释执行多种类型脚本语言。但是发现已经多年不更新，原来是Java 6已经内建Scripting的支持，所以这些第三方的工具也都结束了历史使命。
Java 6自带的实际上是 Mozilla Rhino 的Java Script引擎，它使用JavaScript的语法，可以调用任意Java代码。更多介绍见Java Scripting Programmer&#8217;s Guide. Rhino除了import写法有点特殊外，基本语法和Java代码基本一致。如：
engine.eval("importClass(java.lang.System)");
engine.eval("println(System.currentTimeMillis())");
engine.eval("println('Source: http://timyang.net/java/java-scriptingjava-scripting/')");
于是做了一个简单的socket服务器，把发过来的文本直接执行，然后再把脚本执行产生的内容返回给发送方。目标达成。共40余行代码(包括注释和花括号)，无需任何第三方library。代码如下：
// create a script engine manager
ScriptEngineManager factory = new ScriptEngineManager();
// create a JavaScript engine
ScriptEngine engine = factory.getEngineByName("JavaScript");

while (true) {
    ServerSocket serverSocket = null;
    try {
        [...]]]></description>
			<content:encoded><![CDATA[<p>对于非Web的后台服务程序，经常会碰到这样的需求：</p>
<ol>
<li>动态改变程序运行时参数的能力。如Config.limitValue = 50</li>
<li>动态查看运行时候变量状态的能力，如 print(userMap.size())</li>
<li>执行代码的能力，如 userMap.clear()</li>
</ol>
<p>对于需求1,非Web的程序没法像PHP/JSP那样直接改就生效，往往改了某个值，即使是一个配置参数都需要服务器重启一下。这对于很多线上服务来说成本太高。</p>
<p>对于上述2的需求，通常是编写庞大的后台管理程序来满足。或者是通过增加日志输出，但问题是某些变量只需要偶尔才看一下，因此很多系统中大部分日志开销基本上是无用的。</p>
<p>对于需求3,只有通过在IDE的debug模式下才能达到。</p>
<p>我觉得所有的后台程序都应该具备这样的能力，为了满足以上需求，于是考虑在所有程序里面嵌入一个小型的解释脚本引擎来实现。就像很多游戏程序嵌入Lua/Python来动态执行代码目的一样。</p>
<p>今天先说下Java中的实现方法，几年前用过<a href="http://www.beanshell.org/" target="_blank">BeanShell</a>, 可以在Java VM里面解释执行多种类型脚本语言。但是发现已经多年不更新，原来是Java 6已经内建Scripting的支持，所以这些第三方的工具也都结束了历史使命。</p>
<p><span><span>Java 6自带的实际上是 <a href="http://www.mozilla.org/rhino">Mozilla Rhino</a> 的Java Script引擎，它使用JavaScript的语法，可以调用任意Java代码。</span></span>更多介绍见<a href="http://java.sun.com/javase/6/docs/technotes/guides/scripting/programmer_guide/index.html" target="_blank">Java Scripting Programmer&#8217;s Guide</a>. <span><span>Rhino除了import写法有点特殊外，基本语法和Java代码基本一致。如：</span></span></p>
<pre>engine.eval("importClass(java.lang.System)");
engine.eval("println(System.currentTimeMillis())");
engine.eval("println('Source: <a href="http://timyang.net/java/java-scriptingjava-scripting/">http://timyang.net/java/java-scriptingjava-scripting/</a>')");</pre>
<p>于是做了一个简单的socket服务器，把发过来的文本直接执行，然后再把脚本执行产生的内容返回给发送方。目标达成。共40余行代码(包括注释和花括号)，无需任何第三方library。代码如下：</p>
<pre>// create a script engine manager
ScriptEngineManager factory = new ScriptEngineManager();
// create a JavaScript engine
ScriptEngine engine = factory.getEngineByName("JavaScript");

while (true) {
    ServerSocket serverSocket = null;
    try {
        serverSocket = new ServerSocket(4444, 50, InetAddress.getByName("localhost"));
    } catch (IOException e) {
        System.err.println("Could not listen on port: 4444.");
        System.exit(1);
    }

    Socket clientSocket = null;
    try {
        clientSocket = serverSocket.accept();
    } catch (IOException e) {
        System.err.println("Accept failed.");
        System.exit(1);
    }

    PrintWriter out = new PrintWriter(clientSocket.getOutputStream(),
            true);
    BufferedReader in = new BufferedReader(new InputStreamReader(
            clientSocket.getInputStream()));
    String inputLine, outputLine;

    while ((inputLine = in.readLine()) != null) {
        if ("quit".equals(inputLine))
                break;
        try {
            // evaluate JavaScript code from String
            out.println(engine.eval(inputLine));
        } catch (Exception e) {
            out.println("error:" + e.getMessage());
        }
    }
    out.close();
    in.close();
    clientSocket.close();
    serverSocket.close();
}</pre>
<p>启动程序之后只要 telnet localhost 4444 就可以执行任意代码并实时查看返回结果。</p>
<p>注意上面为了安全起见，只绑定了localhost地址，防止此功能被外部用户恶意使用。</p>
Similar Posts:<ul><li><a href="http://timyang.net/programming/c-erlang-java-performance/" rel="bookmark" title="November 11, 2009">C, Erlang, Java and Go Web Server performance test</a></li>

<li><a href="http://timyang.net/architecture/friendfeed-like-aggregator/" rel="bookmark" title="April 3, 2009">Ideas for creating a friendfeed like feed aggregator system</a></li>

<li><a href="http://timyang.net/linux/gearman-monitor/" rel="bookmark" title="August 26, 2009">利用Gearman来实现远程监控与管理</a></li>

<li><a href="http://timyang.net/lua/lua-coroutine-vs-java-wait-notify/" rel="bookmark" title="April 27, 2009">Lua coroutine vs Java wait/notify</a></li>

<li><a href="http://timyang.net/python/python-rest/" rel="bookmark" title="February 12, 2009">用Python实现CRUD功能REST服务</a></li>
</ul><!-- Similar Posts took 12.295 ms -->]]></content:encoded>
			<wfw:commentRss>http://timyang.net/java/java-scripting/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Lua coroutine vs Java wait/notify</title>
		<link>http://timyang.net/lua/lua-coroutine-vs-java-wait-notify/</link>
		<comments>http://timyang.net/lua/lua-coroutine-vs-java-wait-notify/#comments</comments>
		<pubDate>Mon, 27 Apr 2009 14:39:07 +0000</pubDate>
		<dc:creator>Tim</dc:creator>
				<category><![CDATA[Lua]]></category>
		<category><![CDATA[coroutine]]></category>
		<category><![CDATA[Java]]></category>

		<guid isPermaLink="false">http://timyang.net/?p=107</guid>
		<description><![CDATA[在上文Lua coroutine 不一样的多线程编程思路 中想到coroutine的运行机制跟Java中的wait/notify很相似，所以写了一个简单程序比较一下。
源代码
Lua code
co = coroutine.create(function(loops)
    for i = 1, loops do
        coroutine.yield()
    end
end)

local x = os.clock()
local loops = 100 * 1000 * 1000
coroutine.resume(co, loops)
for i = 1, loops do
    coroutine.resume(co)
end
print(string.format("elapsed time: %.2f\n", os.clock() - x))
Java code
public class [...]]]></description>
			<content:encoded><![CDATA[<p>在上文<a href="/lua/lua-coroutine/">Lua coroutine 不一样的多线程编程思路 </a>中想到coroutine的运行机制跟Java中的wait/notify很相似，所以写了一个简单程序比较一下。</p>
<h2>源代码</h2>
<p>Lua code</p>
<pre>co = coroutine.create(function(loops)
    for i = 1, loops do
        coroutine.yield()
    end
end)

local x = os.clock()
local loops = 100 * 1000 * 1000
coroutine.resume(co, loops)
for i = 1, loops do
    coroutine.resume(co)
end
print(string.format("elapsed time: %.2f\n", os.clock() - x))</pre>
<p>Java code</p>
<pre>public class TestWait {
    public static void main(String[] args) {
        WaitClass wc = new WaitClass();
        wc.start();
        int loops = 100 * 1000 * 1000;
        long t1 = System.currentTimeMillis();
        for (int i = 0; i &lt; loops; i++) {
            synchronized (wc) {
                wc.notify();
            }
        }
        long t2 = System.currentTimeMillis();
        System.out.println("elapsed time: " + (t2 - t1) / 1000l);
    }
}

class WaitClass extends Thread {
    public void run() {
        while (true) {
            synchronized (this) {
                try {
                    this.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}</pre>
<h2>运行结果</h2>
<p>Lua elapsed time: 53.36<br />
Java elapsed time: 51</p>
<h2>CPU占用</h2>
<p>运行环境：4core XEON</p>
<p>Lua 1CPU 100%, 其他CPU0%, total 25% (其中CPU sys 0%)</p>
<p>Java 2个CPU 40%-50%, 其他CPU 0%, total 25% (其中CPU sys 5%-10%)</p>
<p>从结果看，coroutine只利用了一个CPU, 和原理所说完全一致。</p>
<p>Java利用了2个CPU, 各占用了50%的CPU时间运行和50%的时间等待，和设计也一致。另外Java用了5-10%的sys CPU时间用于线程context switch</p>
<h2>结论</h2>
<p>虽然这两种程序没有直接可比性，但仍然可以看出一些有趣的地方：</p>
<ul>
<li>Lua虽然在各种性能评比中performance比Java低一个数量级，但在这个场景中也跑平了Java</li>
<li>Java为了调用notify/wait, 用了同步锁，因此测试场景对Java不利。</li>
</ul>
<h2>再谈coroutine应用场景</h2>
<p>今天又看到qiezi的文章<a href="http://qiezi.javaeye.com/blog/179949" target="_blank">并发编程模型：Thread, Coroutine, Callback &#8230; </a>分析得很深入，对这方面感兴趣的可以进一步去深入了解。</p>
<p>另外qiezi在<a href="Coroutine在并发程序中的应用" target="_blank">Coroutine在并发程序中的应用</a>中提到四种场景，可以理解是对我上篇文章对coroutine应用场景的一种答案。</p>
<ol>
<li>状态机。</li>
<li>异步IO操作：异步IO操作通常是发起一个IO请求，由操作系统完成以后回调指定的方法或者使用其它方式通知。</li>
<li>高并发网络服务器，高并发服务器除了要处理场景一的情况外，可能还要结合场景二，多线程方案有时候完全不能接受，更多的是基于事件、异步IO或者是混合事件和多线程的模型。</li>
<li>客户端并发应用</li>
</ol>
<p>但是我还是觉得存在疑虑，后面几种我觉得用多线程/线程池模式也可以很好解决。其实select/epoll异步IO方式跟多线程并不矛盾。多线程并不代表每个线程需要recv阻塞在那里。目前网络服务器的多线程通常是指业务逻辑处理部分使用多线程。比如Java中用mina来处理连接(相当于epoll)，mina在收到数据包之后再分发给负责业务逻辑的thread pool处理。如果是CPU密集型任务，简单把线程池的线程数设成CPU数即可达到性能最佳。这时如果把线程数设成1，就很类似coroutine模式了。而Java模式所增加的消耗，主要是new runnable class以及线程池调度的开销。</p>
Similar Posts:<ul><li><a href="http://timyang.net/lua/lua-coroutine/" rel="bookmark" title="April 26, 2009">Lua coroutine 不一样的多线程编程思路</a></li>

<li><a href="http://timyang.net/java/java_gc_tunning/" rel="bookmark" title="January 7, 2009">Java垃圾回收调优</a></li>

<li><a href="http://timyang.net/architecture/twitter-cache-architecture/" rel="bookmark" title="October 28, 2009">Twitter架构图(cache篇)</a></li>

<li><a href="http://timyang.net/python/python-thread-socket-server/" rel="bookmark" title="March 8, 2009">Python thread socket server</a></li>

<li><a href="http://timyang.net/programming/lighttpd-mod_cache-twitter/" rel="bookmark" title="July 5, 2009">关于阙宏宇lighttpd与mod_cache在twitter上的一些讨论</a></li>
</ul><!-- Similar Posts took 12.272 ms -->]]></content:encoded>
			<wfw:commentRss>http://timyang.net/lua/lua-coroutine-vs-java-wait-notify/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Thrift and Protocol Buffers performance in Java Round 2</title>
		<link>http://timyang.net/programming/thrift-protocol-buffers-performance-2/</link>
		<comments>http://timyang.net/programming/thrift-protocol-buffers-performance-2/#comments</comments>
		<pubDate>Fri, 17 Apr 2009 02:29:40 +0000</pubDate>
		<dc:creator>Tim</dc:creator>
				<category><![CDATA[编程]]></category>
		<category><![CDATA[English]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[protocol buffers]]></category>
		<category><![CDATA[thrift]]></category>

		<guid isPermaLink="false">http://timyang.net/?p=91</guid>
		<description><![CDATA[In my last test Thrift and Protocol Buffers performance in Java, Some comments told me that there are some tuning parameter for Protocol Buffer which can improve performance magically. The parameter was not turn on by default. I added
option optimize_for = SPEED
to the proto file, and re-generated the Java class, and the result:
Thrift Loop    : [...]]]></description>
			<content:encoded><![CDATA[<p>In my last test <a href="http://timyang.net/programming/thrift-protocol-buffers-performance-java/" target="_blank">Thrift and Protocol Buffers performance in Java</a>, Some comments told me that there are some tuning parameter for Protocol Buffer which can improve performance magically. The parameter was not turn on by default. I added<br />
option optimize_for = SPEED<br />
to the proto file, and re-generated the Java class, and the result:</p>
<pre>Thrift Loop    : 10,000,000
Get object     : 14,394msec
Serdes thrift  : 37,671msec
Objs per second: 265,456
Total bytes    : 1,130,000,000

ProtoBuf Loop  : 10,000,000
Get object     : 8,170msec
Serdes protobuf: 33,054msec
Objs per second: 302,535
Total bytes    : 829,997,866
</pre>
<p>From the result, Protocol Buffers is 1.1 times faster than Thrift!</p>
<p>And from the Google Protocol Buffers group, why the optimize for speed was not turn on by default.</p>
<blockquote><p>When using C++ or Java protocol buffers, for best performance you need to add a line to your .proto files:</p>
<p>option optimize_for = SPEED;</p>
<p>Otherwise, by default, the compiler optimizes for code size.  Optimizing for code size results in generated code that around a half to a third of the size, but runs an order of magnitude slower&#8230;</p></blockquote>
<p>Here is the <a href="http://groups.google.com/group/protobuf/browse_thread/thread/3ad2fb05be0d8912" target="_blank">original post<br />
</a></p>
Similar Posts:<ul><li><a href="http://timyang.net/programming/thrift-protocol-buffers-performance-java/" rel="bookmark" title="April 2, 2009">Thrift and Protocol Buffers performance in Java</a></li>

<li><a href="http://timyang.net/programming/thrift-protocol-buffers-java-howto/" rel="bookmark" title="April 2, 2009">Thrift, Protocol Buffers installation and Java code howto</a></li>

<li><a href="http://timyang.net/data/mcdb-tt-redis/" rel="bookmark" title="August 11, 2009">MemcacheDB, Tokyo Tyrant, Redis performance test</a></li>

<li><a href="http://timyang.net/programming/c-erlang-java-performance/" rel="bookmark" title="November 11, 2009">C, Erlang, Java and Go Web Server performance test</a></li>

<li><a href="http://timyang.net/linux/gearman-monitor/" rel="bookmark" title="August 26, 2009">利用Gearman来实现远程监控与管理</a></li>
</ul><!-- Similar Posts took 11.465 ms -->]]></content:encoded>
			<wfw:commentRss>http://timyang.net/programming/thrift-protocol-buffers-performance-2/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Java垃圾回收调优</title>
		<link>http://timyang.net/java/java_gc_tunning/</link>
		<comments>http://timyang.net/java/java_gc_tunning/#comments</comments>
		<pubDate>Wed, 07 Jan 2009 12:04:41 +0000</pubDate>
		<dc:creator>Tim</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[GC]]></category>

		<guid isPermaLink="false">http://timyang.net/?p=17</guid>
		<description><![CDATA[在Java中，通常通讯类型的服务器对GC(Garbage Collection)比较敏感。通常通讯服务器每秒需要处理大量进出的数据包，需要解析，分解成不同的业务逻辑对象并做相关的业务处理，这样会导致大量的临时对象被创建和回收。同时服务器如果需要同时保存用户状态的话，又会产生很多永久的对象，比如用户session。业务越复杂的应用往往用户session包含的引用对象就越多。这样在极端情况下会发生两件事情，long gc pause time 或 out of memory。
一，要解决long pause time首先要了解JVM中heap的结构

Java Heap为什么要分成几个不同的代(generation)? 由于80%-98%的对象的生存周期很短，大部分新对象存放在young generation可以很高效的回收，避免遍历所有对象。
young与old中内存分配的算法完全不同。young generation中由于存活的很少，要mark, sweep 然后再 compact 剩余的对象比较耗时，干脆把 live object copy 到另外一个空间更高效。old generation完全相反，里面的 live object 变化较少。因此采用 mark-sweep-compact更合适。

二，Java中四种垃圾回收算法
Java中有四种不同的回收算法，对应的启动参数为
–XX:+UseSerialGC
–XX:+UseParallelGC
–XX:+UseParallelOldGC
–XX:+UseConcMarkSweepGC
1. Serial Collector
大部分平台或者强制 java -client 默认会使用这种。
young generation算法 = serial
old generation算法 = serial (mark-sweep-compact)
这种方法的缺点很明显，stop-the-world, 速度慢。服务器应用不推荐使用。
2. Parallel Collector
在linux x64上默认是这种，其他平台要加 java -server 参数才会默认选用这种。
young = parallel，多个thread同时copy
old = mark-sweep-compact = 1
优点：新生代回收更快。因为系统大部分时间做的gc都是新生代的，这样提高了throughput(cpu用于非gc时间)
缺点：当运行在8G/16G server上old generation [...]]]></description>
			<content:encoded><![CDATA[<p>在Java中，通常通讯类型的服务器对GC(Garbage Collection)比较敏感。通常通讯服务器每秒需要处理大量进出的数据包，需要解析，分解成不同的业务逻辑对象并做相关的业务处理，这样会导致大量的临时对象被创建和回收。同时服务器如果需要同时保存用户状态的话，又会产生很多永久的对象，比如用户session。业务越复杂的应用往往用户session包含的引用对象就越多。这样在极端情况下会发生两件事情，long gc pause time 或 out of memory。</p>
<p>一，要解决long pause time首先要了解JVM中heap的结构</p>
<div id="attachment_18" class="wp-caption alignnone" style="width: 519px"><img class="size-full wp-image-18" title="java gc heap" src="http://timyang.net/blog/wp-content/uploads/2009/01/java-gc.png" alt="java gc heap" width="509" height="398" /><p class="wp-caption-text">java gc heap</p></div>
<ul>
<li>Java Heap为什么要分成几个不同的代(generation)? 由于80%-98%的对象的生存周期很短，大部分新对象存放在young generation可以很高效的回收，避免遍历所有对象。</li>
<li>young与old中内存分配的算法完全不同。young generation中由于存活的很少，要mark, sweep 然后再 compact 剩余的对象比较耗时，干脆把 live object copy 到另外一个空间更高效。old generation完全相反，里面的 live object 变化较少。因此采用 mark-sweep-compact更合适。</li>
</ul>
<p>二，Java中四种垃圾回收算法</p>
<p>Java中有四种不同的回收算法，对应的启动参数为<br />
–XX:+UseSerialGC<br />
–XX:+UseParallelGC<br />
–XX:+UseParallelOldGC<br />
–XX:+UseConcMarkSweepGC</p>
<p>1. Serial Collector<br />
大部分平台或者强制 java -client 默认会使用这种。<br />
young generation算法 = serial<br />
old generation算法 = serial (mark-sweep-compact)<br />
这种方法的缺点很明显，stop-the-world, 速度慢。服务器应用不推荐使用。</p>
<p>2. Parallel Collector<br />
在linux x64上默认是这种，其他平台要加 java -server 参数才会默认选用这种。<br />
young = parallel，多个thread同时copy<br />
old = mark-sweep-compact = 1<br />
优点：新生代回收更快。因为系统大部分时间做的gc都是新生代的，这样提高了throughput(cpu用于非gc时间)<br />
缺点：当运行在8G/16G server上old generation live object太多时候pause time过长</p>
<p>3. Parallel Compact Collector (ParallelOld)<br />
young = parallel = 2<br />
old = parallel，分成多个独立的单元，如果单元中live object少则回收，多则跳过<br />
优点：old old generation上性能较 parallel 方式有提高<br />
缺点：大部分server系统old generation内存占用会达到60%-80%, 没有那么多理想的单元live object很少方便迅速回收，同时compact方面开销比起parallel并没明显减少。</p>
<p>4. Concurent Mark-Sweep(CMS) Collector<br />
young generation = parallel collector = 2<br />
old = cms<br />
同时不做 compact 操作。<br />
优点：pause time会降低, pause敏感但CPU有空闲的场景需要建议使用策略4.<br />
缺点：cpu占用过多，cpu密集型服务器不适合。另外碎片太多，每个object的存储都要通过链表连续跳n个地方，空间浪费问题也会增大。</p>
<p>几条经验：<br />
1. java -server<br />
2. 设置Xms=Xmx=3/4物理内存<br />
3. 如果是CPU密集型服务器，使用–XX:+UseParallelOldGC, 否则–XX:+UseConcMarkSweepGC<br />
4. 新生代,Parallel/ParallelOld可设大于Xmx1/4，CMS可设小，小于Xmx1/4<br />
5. 优化程序，特别是每个用户的session中的集合类等。我们的一个模块中session中曾经为每个用户使用了一个ConcurrentHashMap, 里面通常只有几条记录，后来改成数组之后，每台机大概节约了1~2G内存。</p>
<p>不过总的说来，Java的GC算法感觉是业界最成熟的，目前很多其他语言或者框架也都支持GC了，但大多数都是只达到Java Serial gc这种层面，甚至分generation都未考虑。JDK7里面针对CMS又进行了一种改进，会采用一种G1(Garbage-First Garbage Collection)的算法。实际上<a href="http://research.sun.com/jtech/pubs/04-g1-paper-ismm.pdf" target="_blank">Garbage-First paper</a>(PDF) 2004年已经出来了，相信到JDK7已经可以用于严格生产环境，有时间也会进一步介绍一下G1。<br />
另外在今年的Sun Tech Days上<a href="http://blogs.sun.com/joeys/" target="_blank">Joey Shen</a>讲的<a href="http://download.developers.sun.com.cn/event/sun_tech_day_china/2008/20081122_beijing_day2/track1/6_TD09_JavaPerformance_JoeyS.pdf" target="_blank">Improving Java Performance</a>(PDF)也是一个很好的Java GC调优的入门教程。</p>
Similar Posts:<ul><li><a href="http://timyang.net/programming/thrift-protocol-buffers-performance-java/" rel="bookmark" title="April 2, 2009">Thrift and Protocol Buffers performance in Java</a></li>

<li><a href="http://timyang.net/programming/thrift-protocol-buffers-performance-2/" rel="bookmark" title="April 17, 2009">Thrift and Protocol Buffers performance in Java Round 2</a></li>

<li><a href="http://timyang.net/programming/thrift-protocol-buffers-java-howto/" rel="bookmark" title="April 2, 2009">Thrift, Protocol Buffers installation and Java code howto</a></li>

<li><a href="http://timyang.net/lua/lua-coroutine-vs-java-wait-notify/" rel="bookmark" title="April 27, 2009">Lua coroutine vs Java wait/notify</a></li>

<li><a href="http://timyang.net/architecture/consistent-hashing-practice/" rel="bookmark" title="September 6, 2009">某分布式应用实践一致性哈希的一些问题</a></li>
</ul><!-- Similar Posts took 20.813 ms -->]]></content:encoded>
			<wfw:commentRss>http://timyang.net/java/java_gc_tunning/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>
