<?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; English</title>
	<atom:link href="http://timyang.net/tag/english/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.221 ms -->]]></content:encoded>
			<wfw:commentRss>http://timyang.net/programming/c-erlang-java-performance/feed/</wfw:commentRss>
		<slash:comments>64</slash:comments>
		</item>
		<item>
		<title>MemcacheDB, Tokyo Tyrant, Redis performance test</title>
		<link>http://timyang.net/data/mcdb-tt-redis/</link>
		<comments>http://timyang.net/data/mcdb-tt-redis/#comments</comments>
		<pubDate>Tue, 11 Aug 2009 12:16:58 +0000</pubDate>
		<dc:creator>Tim</dc:creator>
				<category><![CDATA[data]]></category>
		<category><![CDATA[English]]></category>
		<category><![CDATA[memcachedb]]></category>
		<category><![CDATA[redis]]></category>
		<category><![CDATA[tokyo cabinet]]></category>
		<category><![CDATA[tokyo tyrant]]></category>

		<guid isPermaLink="false">http://timyang.net/?p=361</guid>
		<description><![CDATA[I had tested the following key-value store for set() and get()

MemcacheDB, use memcached client protocol.
Tokyo Tyrant (Tokyo Cabinet), use memcached client protocol
Redis, use JRedis Java client

1. Test environment
1.1 Hardware/OS
2 Linux boxes in a LAN, 1 server and 1 test client
Linux Centos 5.2 64bit
Intel(R) Xeon(R) CPU E5410  @ 2.33GHz (L2 cache: 6M), Quad-Core * 2
8G memory
SCSI [...]]]></description>
			<content:encoded><![CDATA[<p>I had tested the following key-value store for set() and get()</p>
<ul>
<li><a href="http://memcachedb.org/">MemcacheDB</a>, use memcached client protocol.</li>
<li><a href="http://tokyocabinet.sourceforge.net/tyrantdoc/">Tokyo Tyrant</a> (<a href="http://tokyocabinet.sourceforge.net/">Tokyo Cabinet</a>), use memcached client protocol</li>
<li><a href="http://code.google.com/p/redis/">Redis</a>, use <a href="http://code.google.com/p/jredis/">JRedis</a> Java client</li>
</ul>
<h2>1. Test environment</h2>
<h3>1.1 Hardware/OS</h3>
<p>2 Linux boxes in a 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>
<h3>1.2 Software version</h3>
<p>db-4.7.25.tar.gz<br />
libevent-1.4.11-stable.tar.gz<br />
memcached-1.2.8.tar.gz<br />
memcachedb-1.2.1-beta.tar.gz<br />
redis-0.900_2.tar.gz<br />
tokyocabinet-1.4.9.tar.gz<br />
tokyotyrant-1.1.9.tar.gz</p>
<h3>1.3 Configuration</h3>
<p><strong>Memcachedb startup parameter</strong><br />
Test 100 bytes<br />
./memcachedb -H /data5/kvtest/bdb/data -d -p 11212 -m 2048 <strong>-N -L 8192</strong><br />
(Update: As mentioned by <a href="http://stvchu.org/">Steve</a>, the 100-byte-test missed the -N paramter, so I added it and updated the data)<br />
Test 20k bytes<br />
./memcachedb -H /data5/kvtest/mcdb/data -d -p 11212 -b 21000 -N -m 2048</p>
<p><strong>Tokyo Tyrant (Tokyo Cabinet) configuration</strong><br />
Use default Tokyo Tyrant sbin/ttservctl<br />
use .tch database, hashtable database</p>
<p>ulimsiz=&#8221;256m&#8221;<br />
sid=1<br />
dbname=&#8221;$basedir/casket.tch#bnum=50000000&#8243; # default 1M is not enough!<br />
maxcon=&#8221;65536&#8243;<br />
retval=0</p>
<p><strong>Redis configuration</strong><br />
timeout 300<br />
save 900 1<br />
save 300 10<br />
save 60 10000<br />
# no maxmemory settings</p>
<h3>1.4 Test client</h3>
<p>Client in Java, JDK1.6.0, 16 threads<br />
Use Memcached client java_memcached-release_2.0.1.jar<br />
<a href="http://code.google.com/p/jredis/">JRedis</a> client for Redis test, another <a href="http://code.google.com/p/jdbc-redis/">JDBC-Redis</a> has poor performance.</p>
<h2>2. Small data size test result</h2>
<p>Test 1, 1-5,000,000 as key, 100 bytes string value, do set, then get test, all get test has result.<br />
Request per second(mean)<img class="alignnone size-full wp-image-374" title="key-value-performance-1(Update)" src="http://timyang.net/blog/wp-content/uploads/2009/08/key-value-performance-11.png" alt="key-value-performance-1(Update)" width="652" height="401" /></p>
<table style="width: 270pt; border-collapse: collapse;" border="0" cellspacing="0" cellpadding="0" width="359">
<colgroup span="1">
<col style="width: 130pt;" span="1" width="173"></col>
<col style="width: 70pt;" span="2" width="93"></col>
</colgroup>
<tbody>
<tr style="height: 15.75pt;" height="21">
<td class="xl25" style="border: medium none #d4d0c8; width: 130pt; height: 15.75pt; background-color: transparent;" width="173" height="21"><span style="font-size: small; font-family: Times New Roman;"><strong>Store</strong></span></td>
<td class="xl25" style="border: medium none #d4d0c8; width: 70pt; background-color: transparent;" width="93"><span style="font-size: small; font-family: Times New Roman;"><strong>Write</strong></span></td>
<td class="xl25" style="border: medium none #d4d0c8; width: 70pt; background-color: transparent;" width="93"><strong><span style="font-size: small; font-family: Times New Roman;">Read</span></strong></td>
</tr>
<tr style="height: 15.75pt;" height="21">
<td class="xl24" style="border: medium none #d4d0c8; height: 15.75pt; background-color: transparent;" height="21"><span style="font-size: small; font-family: Times New Roman;">Memcached</span></td>
<td class="xl26" style="background-color: transparent; border: #d4d0c8;" align="right"><span style="font-size: small; font-family: Times New Roman;">55,989 </span></td>
<td class="xl26" style="background-color: transparent; border: #d4d0c8;" align="right"><span style="font-size: small; font-family: Times New Roman;">50,974 </span></td>
</tr>
<tr style="height: 15.75pt;" height="21">
<td class="xl24" style="border: medium none #d4d0c8; height: 15.75pt; background-color: transparent;" height="21"><span style="font-size: small; font-family: Times New Roman;">Memcachedb</span></td>
<td class="xl26" style="background-color: transparent; border: #d4d0c8;" align="right"><span style="font-size: small; font-family: Times New Roman;">25,583 </span></td>
<td class="xl26" style="background-color: transparent; border: #d4d0c8;" align="right"><span style="font-size: small; font-family: Times New Roman;">35,260 </span></td>
</tr>
<tr style="height: 15.75pt;" height="21">
<td class="xl24" style="border: medium none #d4d0c8; height: 15.75pt; background-color: transparent;" height="21"><span style="font-size: small; font-family: Times New Roman;">Tokyo Tyrant</span></td>
<td class="xl26" style="background-color: transparent; border: #d4d0c8;" align="right"><span style="font-size: small; font-family: Times New Roman;">42,988 </span></td>
<td class="xl26" style="background-color: transparent; border: #d4d0c8;" align="right"><span style="font-size: small; font-family: Times New Roman;">46,238 </span></td>
</tr>
<tr style="height: 15.75pt;" height="21">
<td class="xl24" style="border: medium none #d4d0c8; height: 15.75pt; background-color: transparent;" height="21"><span style="font-size: small; font-family: Times New Roman;">Redis</span></td>
<td class="xl26" style="background-color: transparent; border: #d4d0c8;" align="right"><span style="font-size: small; font-family: Times New Roman;">85,765 </span></td>
<td class="xl26" style="background-color: transparent; border: #d4d0c8;" align="right"><span style="font-size: small; font-family: Times New Roman;">71,708 </span></td>
</tr>
</tbody>
</table>
<p><strong>Server Load Average</strong></p>
<table style="width: 249pt; border-collapse: collapse;" border="0" cellspacing="0" cellpadding="0" width="332">
<colgroup span="1">
<col style="width: 77pt;" span="1" width="102"></col>
<col style="width: 86pt;" span="2" width="115"></col>
</colgroup>
<tbody>
<tr style="height: 15.75pt;" height="21">
<td class="xl25" style="border: medium none #d4d0c8; width: 77pt; height: 15.75pt; background-color: transparent;" width="102" height="21"><span style="font-size: small; font-family: Times New Roman;"><strong>Store</strong></span></td>
<td class="xl25" style="border: medium none #d4d0c8; width: 86pt; background-color: transparent;" width="115"><span style="font-size: small; font-family: Times New Roman;"><strong>Write</strong></span></td>
<td class="xl25" style="border: medium none #d4d0c8; width: 86pt; background-color: transparent;" width="115"><strong><span style="font-size: small; font-family: Times New Roman;">Read</span></strong></td>
</tr>
<tr style="height: 15.75pt;" height="21">
<td class="xl24" style="border: medium none #d4d0c8; height: 15.75pt; background-color: transparent;" height="21"><span style="font-size: small; font-family: Times New Roman;">Memcached</span></td>
<td class="xl26" style="background-color: transparent; border: #d4d0c8;"><span style="font-size: small; font-family: Times New Roman;">1.80, 1.53, 0.87</span></td>
<td class="xl26" style="background-color: transparent; border: #d4d0c8;"><span style="font-size: small; font-family: Times New Roman;">1.17, 1.16, 0.83</span></td>
</tr>
<tr style="height: 15.75pt;" height="21">
<td class="xl24" style="border: medium none #d4d0c8; height: 15.75pt; background-color: transparent;" height="21"><span style="font-size: small; font-family: Times New Roman;">MemcacheDB</span></td>
<td class="xl26" style="background-color: transparent; border: #d4d0c8;"><span style="font-size: small; font-family: Times New Roman;">1.44, 0.93, 0.64</span></td>
<td class="xl26" style="background-color: transparent; border: #d4d0c8;"><span style="font-size: small; font-family: Times New Roman;">4.35, 1.94, 1.05</span></td>
</tr>
<tr style="height: 15.75pt;" height="21">
<td class="xl24" style="border: medium none #d4d0c8; height: 15.75pt; background-color: transparent;" height="21"><span style="font-size: small; font-family: Times New Roman;">Tokyo Tyrant</span></td>
<td class="xl26" style="background-color: transparent; border: #d4d0c8;"><span style="font-size: small; font-family: Times New Roman;">3.70, 1.71, 1.14</span></td>
<td class="xl26" style="background-color: transparent; border: #d4d0c8;"><span style="font-size: small; font-family: Times New Roman;">2.98, 1.81, 1.26</span></td>
</tr>
<tr style="height: 15.75pt;" height="21">
<td class="xl24" style="border: medium none #d4d0c8; height: 15.75pt; background-color: transparent;" height="21"><span style="font-size: small; font-family: Times New Roman;">Redis</span></td>
<td class="xl26" style="background-color: transparent; border: #d4d0c8;"><span style="font-size: small; font-family: Times New Roman;">1.06, 0.32, 0.18</span></td>
<td class="xl26" style="background-color: transparent; border: #d4d0c8;"><span style="font-size: small; font-family: Times New Roman;">1.56, 1.00, 0.54</span></td>
</tr>
</tbody>
</table>
<h2>3. Larger data size test result</h2>
<p>Test 2, 1-500,000 as key, 20k bytes string value, do set, then get test, all get test has result.<br />
Request per second(mean)<br />
<strong>(Aug 13 Update: fixed a bug on get() that read non-exist key)</strong><br />
<img class="alignnone size-full wp-image-385" title="key-value-performance-2(update)" src="http://timyang.net/blog/wp-content/uploads/2009/08/key-value-performance-21.png" alt="key-value-performance-2(update)" width="646" height="378" /></p>
<table style="width: 270pt; border-collapse: collapse;" border="0" cellspacing="0" cellpadding="0" width="359">
<colgroup span="1">
<col style="width: 130pt;" span="1" width="173"></col>
<col style="width: 70pt;" span="2" width="93"></col>
</colgroup>
<tbody>
<tr style="height: 15.75pt;" height="21">
<td class="xl25" style="border: medium none #d4d0c8; width: 130pt; height: 15.75pt; background-color: transparent;" width="173" height="21"><span style="font-size: small; font-family: Times New Roman;"><strong>Store</strong></span></td>
<td class="xl25" style="border: medium none #d4d0c8; width: 70pt; background-color: transparent;" width="93"><span style="font-size: small; font-family: Times New Roman;"><strong>Write</strong></span></td>
<td class="xl25" style="border: medium none #d4d0c8; width: 70pt; background-color: transparent;" width="93"><strong><span style="font-size: small; font-family: Times New Roman;">Read</span></strong></td>
</tr>
<tr style="height: 15.75pt;" height="21">
<td class="xl24" style="border: medium none #d4d0c8; height: 15.75pt; background-color: transparent;" height="21"><span style="font-size: small; font-family: Times New Roman;">Memcachedb</span></td>
<td class="xl26" style="background-color: transparent; border: #d4d0c8;" align="right"><span style="font-size: small; font-family: Times New Roman;">357 </span></td>
<td class="xl26" style="background-color: transparent; border: #d4d0c8;" align="right"><span style="font-size: small; font-family: Times New Roman;">327 </span></td>
</tr>
<tr style="height: 15.75pt;" height="21">
<td class="xl24" style="border: medium none #d4d0c8; height: 15.75pt; background-color: transparent;" height="21"><span style="font-size: small; font-family: Times New Roman;">Tokyo Tyrant</span></td>
<td class="xl26" style="background-color: transparent; border: #d4d0c8;" align="right"><span style="font-size: small; font-family: Times New Roman;">3,501 </span></td>
<td class="xl26" style="background-color: transparent; border: #d4d0c8;" align="right"><span style="font-size: small; font-family: Times New Roman;">257 </span></td>
</tr>
<tr style="height: 15.75pt;" height="21">
<td class="xl24" style="border: medium none #d4d0c8; height: 15.75pt; background-color: transparent;" height="21"><span style="font-size: small; font-family: Times New Roman;">Redis</span></td>
<td class="xl26" style="background-color: transparent; border: #d4d0c8;" align="right"><span style="font-size: small; font-family: Times New Roman;">1,542 </span></td>
<td class="xl26" style="background-color: transparent; border: #d4d0c8;" align="right"><span style="font-size: small; font-family: Times New Roman;">957 </span></td>
</tr>
</tbody>
</table>
<h2>4. Some notes about the test</h2>
<p>When test Redis server, the memory goes up steadily, consumed all 8G and then use swap(and write speed slow down), after all memory and swap space is used, the client will get exceptions. So use Redis in a productive environment should limit to a small data size. It is another cache solution rather than a persistent storage. <strong>So compare Redis together with MemcacheDB/TC may not fair because Redis actually does not save data to disk during the test</strong>.</p>
<p>Tokyo cabinet and memcachedb are very stable during heavy load, use very little memory in set test and less than physical memory in get test.</p>
<p>MemcacheDB peformance is poor for write large data size(20k).</p>
<p>The call response time was not monitored in this test.</p>
Similar Posts:<ul><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-performance-java/" rel="bookmark" title="April 2, 2009">Thrift and Protocol Buffers performance in Java</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/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/python/python-thread-socket-server/" rel="bookmark" title="March 8, 2009">Python thread socket server</a></li>
</ul><!-- Similar Posts took 9.058 ms -->]]></content:encoded>
			<wfw:commentRss>http://timyang.net/data/mcdb-tt-redis/feed/</wfw:commentRss>
		<slash:comments>42</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 14.031 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>Ideas for creating a friendfeed like feed aggregator system</title>
		<link>http://timyang.net/architecture/friendfeed-like-aggregator/</link>
		<comments>http://timyang.net/architecture/friendfeed-like-aggregator/#comments</comments>
		<pubDate>Fri, 03 Apr 2009 07:46:28 +0000</pubDate>
		<dc:creator>Tim</dc:creator>
				<category><![CDATA[架构]]></category>
		<category><![CDATA[English]]></category>
		<category><![CDATA[feed]]></category>
		<category><![CDATA[friendfeed]]></category>
		<category><![CDATA[microblogging]]></category>
		<category><![CDATA[pubsub]]></category>

		<guid isPermaLink="false">http://timyang.net/?p=84</guid>
		<description><![CDATA[I was invited to join a meeting about implement a friendfeed like feed system. Here are some ideas about requirement and architecture, which I typed on my BlackBerry during the meeting.

Like the friendfeed, The product can import external RSS, so we separate the system into two parts. The rss crawl system and the feed pubsub [...]]]></description>
			<content:encoded><![CDATA[<p>I was invited to join a meeting about implement a <a href="http://www.friendfeed.com/" target="_blank">friendfeed</a> like feed system. Here are some ideas about requirement and architecture, which I typed on my BlackBerry during the meeting.</p>
<ol>
<li>Like the friendfeed, The product can import external RSS, so we separate the system into two parts. The rss crawl system and the feed pubsub system. The pubsub system has no responsbility to grab the feed from source. The feed itself only save feed summary and url.</li>
<li>We decided to use the INBOX approach, which will push the published feed to be saved in all subscriber&#8217;s data table. More information of how this work can refer to <a href="http://www.hueniverse.com/hueniverse/2008/03/on-scaling-a-mi.html" target="_blank">Scaling a Microblogging Service &#8211; Part I</a>.</li>
<li>User&#8217;s homepage is an aggregation result. We choose to return a limited recent real-time date, no infinity pagination. But the user&#8217;s own feed(user&#8217;s profile page) may have a bigger date range.</li>
<li>The unsubscibe logic have two choice, delete or keep the history data from one&#8217;s inbox. We decide to keep them.</li>
<li>If the feed source had been deleted, do we need to delete all references in all subscriber&#8217;s inbox?  If need delete, each feed push to the pubsub system need to have a unique resource id. Another problem is after the source updated whether to publish a new feed or update the current feed?</li>
<li>How to manage the group(QUN in Chinese) feed, deliver to all member&#8217;s inbox? Or share a group inbox?</li>
<li>How to impl the feed comment logic, publish the comment to feed system or design a standalone comment system. We prefer to use a standalone comment system which doesn&#8217;t publish the comment back to the feed system.</li>
<li>Every feed has a media type, such as text, video, image so the subscribe API can only retrieve a limited media type (text for mobile device). And a feed may have tags.</li>
<li>The read/unread count is easy to implement. But the load is heavy. (<a href="http://www.qq.com/" target="_blank">QQ</a> / QQzone may has such logic.)</li>
<li>Need open API for 3rd party client(like twitter client), and RSS feed, may have <a href="http://oauth.net/" target="_blank">OAuth</a> integration.</li>
<li>The storage may like friendfeed&#8217;s mysql schema (see <a href="http://bret.appspot.com/entry/how-friendfeed-uses-mysql" target="_blank">How FriendFeed uses MySQL to store schema-less data</a>) or use Amazon simpledb.</li>
<li>May add support for XMPP <a href="http://xmpp.org/extensions/xep-0060.html" target="_blank">Publish-Subscribe</a>, or <a href="http://xmpp.org/extensions/xep-0163.html" target="_blank">PEP</a>(Personal Eventing Protocol) for pushing realtime time to users in the future.</li>
</ol>
Similar Posts:<ul><li><a href="http://timyang.net/python/python-rest/" rel="bookmark" title="February 12, 2009">用Python实现CRUD功能REST服务</a></li>

<li><a href="http://timyang.net/data/friendfeed-mysql-schema-less/" rel="bookmark" title="October 29, 2009">Friendfeed的MySQL key/value存储</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/sns/facebook-feed/" rel="bookmark" title="June 2, 2009">Facebook的feed格式设计</a></li>

<li><a href="http://timyang.net/web/nginx-module/" rel="bookmark" title="March 17, 2009">如何写nginx module</a></li>
</ul><!-- Similar Posts took 9.281 ms -->]]></content:encoded>
			<wfw:commentRss>http://timyang.net/architecture/friendfeed-like-aggregator/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Thrift and Protocol Buffers performance in Java</title>
		<link>http://timyang.net/programming/thrift-protocol-buffers-performance-java/</link>
		<comments>http://timyang.net/programming/thrift-protocol-buffers-performance-java/#comments</comments>
		<pubDate>Thu, 02 Apr 2009 12:18:54 +0000</pubDate>
		<dc:creator>Tim</dc:creator>
				<category><![CDATA[编程]]></category>
		<category><![CDATA[English]]></category>
		<category><![CDATA[protocol buffers]]></category>
		<category><![CDATA[thrift]]></category>

		<guid isPermaLink="false">http://timyang.net/?p=77</guid>
		<description><![CDATA[I&#8217;ve used Thrift for some log client in our system. I&#8217;m going to use Protocol Buffers as the internal communication protocol between our XMPP servers. But I am hard to believe from the thrift and protocol buffers Python performance comparison, that that Protocol Buffers is 4-10 slower than Thrift. I&#8217;m going to do some similar [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve used <a href="http://incubator.apache.org/thrift/" target="_blank">Thrift</a> for some log client in our system. I&#8217;m going to use <a href="http://code.google.com/apis/protocolbuffers/">Protocol Buffers</a> as the internal communication protocol between our XMPP servers. But I am hard to believe from the <a href="http://bouncybouncy.net/ramblings/posts/thrift_and_protocol_buffers/" target="_blank">thrift and protocol buffers</a> Python performance comparison, that that Protocol Buffers is 4-10 slower than Thrift. I&#8217;m going to do some similar tests on Java.</p>
<p>The test is very similiar as the Python test. the .proto and .thrift file are copied from the above python test.</p>
<p>The .thrift content:</p>
<pre>struct dns_record {
1: string key,
2: string value,
3: string type = 'A',
4: i32 ttl = 86400,
5: string first,
6: string last
}

typedef list&lt;dns_record&gt; biglist

struct dns_response {
1: biglist records
}

service PassiveDns {
biglist search_question(1:string q);
biglist search_answer(1:string q);
}</pre>
<p>The .proto content</p>
<pre>package passive_dns;

message DnsRecord {
required string key = 1;
required string value = 2;
required string first = 3;
required string last = 4;
optional string type = 5 [default = "A"];
optional int32  ttl = 6 [default = 86400];
}

message DnsResponse {
repeated DnsRecord records = 1;
}</pre>
<p>From the document, I learn that the optional and default values are one of the benefits of both serialization libraries. A record that matches the default value does not need to be included in the serialized output.</p>
<p>I wrote up a simple test program to compare thrift, protocol buffers. I tested the serialize and deserialize together, because this is the most called part in most scenarioes.</p>
<p>Test 1: 10,000,000 times</p>
<pre>ProtoBuf Loop  : 10,000,000
Get object     : 15,130msec
Serdes protobuf: 68,600msec
Objs per second: 145,772
Total bytes    : 829,996,683

Thrift Loop    : 10,000,000
Get object     : 12,651msec
Serdes thrift  : 36,904msec
Objs per second: 270,973
Total bytes    : 1,130,000,000</pre>
<p>Test 2: 1,000,000 times</p>
<pre>ProtoBuf Loop  : 1,000,000
Get object     : 1,094msec
Serdes protobuf: 7,467msec
Objs per second: 133,922
Total bytes    : 83,000,419

Thrift Loop    : 1,000,000
Get object     : 524msec
Serdes thrift  : 5,969msec
Objs per second: 167,532
Total bytes    : 113,000,000</pre>
<p>The serde_* functions are the times needed to serialize, and de-serialize the java object to and from a byte[].</p>
<p>The result in Java was that Protocol Buffers 1.2-2 times slower than Thrift. (in the python test was 4~10 times). And PB binary size is smaller than Thrift. I think this is acceptable, and Google may improve the Protocol Buffers performance in the future version.</p>
<p>Download my test code in Java: <a href="http://timyang.net/code/thrift-protocol-buffers-java.tgz">thrift-protocol-buffers-java.tgz</a>,</p>
<p>More information about thrift and protocol buffers: <a href="http://timyang.net/programming/thrift-protocol-buffers-java-howto/">Thrift, Protocol Buffers installation and Java code howto</a></p>
<p>Update: There is another <a href="http://stuartsierra.com/2008/07/10/thrift-vs-protocol-buffers" target="_blank">Thrift vs. Protocol Buffers</a> compare non-performance factors.</p>
<p>UPDATE 2 (Apr 17): There is a performance tuning parameter optimize_for = SPEED (thanks <a href="http://stvchu.org/" target="_blank">Steve Chu</a>) for Protocol Buffers,  please see my next performance tests <a href="http://timyang.net/programming/thrift-protocol-buffers-performance-2/">Thrift and Protocol Buffers performance in Java Round 2</a></p>
Similar Posts:<ul><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/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 14.120 ms -->]]></content:encoded>
			<wfw:commentRss>http://timyang.net/programming/thrift-protocol-buffers-performance-java/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Thrift, Protocol Buffers installation and Java code howto</title>
		<link>http://timyang.net/programming/thrift-protocol-buffers-java-howto/</link>
		<comments>http://timyang.net/programming/thrift-protocol-buffers-java-howto/#comments</comments>
		<pubDate>Thu, 02 Apr 2009 11:44:27 +0000</pubDate>
		<dc:creator>Tim</dc:creator>
				<category><![CDATA[编程]]></category>
		<category><![CDATA[English]]></category>
		<category><![CDATA[protocol buffers]]></category>
		<category><![CDATA[thrift]]></category>

		<guid isPermaLink="false">http://timyang.net/?p=71</guid>
		<description><![CDATA[I. Thrift installation and Java code
1. build and install thrift
install boost
cd &#60;boost_root&#62;/tools/jam
./build_dist.sh
# linux* will depends the platform
cp stage/bin.linux*/bjam &#60;boost_root&#62;
# build boost, use bjam will faster
cd &#60;boost_root&#62;
./configure &#8211;without-icu &#8211;prefix=/usr/local/boost
./bjam -toolset=gcc &#8211;build-type=release install &#8211;prefix=/usr/local/boost
# build thrift
./bootstrap.sh
./configure &#8211;with-boost=/usr/local
make
make install
2. Build Thrift java library
install apache ant if necessary
cd lib/java/
ant
get libthrift.jar
3. Create .thrift file and gen Java code
(See http://wiki.apache.org/thrift/Tutorial for [...]]]></description>
			<content:encoded><![CDATA[<h1>I. Thrift installation and Java code</h1>
<h2>1. build and install thrift</h2>
<p>install boost<br />
cd &lt;boost_root&gt;/tools/jam<br />
./build_dist.sh<br />
# linux* will depends the platform<br />
cp stage/bin.linux*/bjam &lt;boost_root&gt;<br />
# build boost, use bjam will faster<br />
cd &lt;boost_root&gt;<br />
./configure &#8211;without-icu &#8211;prefix=/usr/local/boost<br />
./bjam -toolset=gcc &#8211;build-type=release install &#8211;prefix=/usr/local/boost</p>
<p># build thrift<br />
./bootstrap.sh<br />
./configure &#8211;with-boost=/usr/local<br />
make<br />
make install</p>
<h2>2. Build Thrift java library</h2>
<p>install apache ant if necessary</p>
<p>cd lib/java/<br />
ant</p>
<p>get libthrift.jar</p>
<h2>3. Create .thrift file and gen Java code</h2>
<p>(See <a href="http://wiki.apache.org/thrift/Tutorial" target="_blank">http://wiki.apache.org/thrift/Tutorial</a> for more .thrift tutorial info)<br />
tim.thrift</p>
<pre>struct dns_record {
1: string key,
2: string value,
3: string type = 'A',
4: i32 ttl = 86400,
5: string first,
6: string last
}

service TestDns {
dns_record test(1:string q);
}</pre>
<p>&lt;thrift_root&gt;/bin/thrift &#8211;gen java tim.thrift<br />
code will be generated in gen-java/*.java</p>
<h2>4. Write java code</h2>
<pre>// new object
dns_record dr = new dns_record(key, value, type, ttl, first, last)
// serialize
TSerializer serializer = new TSerializer(new TBinaryProtocol.Factory());
TDeserializer deserializer = new TDeserializer(new TBinaryProtocol.Factory());
byte[] bytes = serializer.serialize(dr);</pre>
<p>see also: <a href="thrift, protocol buffer install and java howto" target="_blank">http://wiki.apache.org/thrift/ThriftUsageJava</a></p>
<h1>II. Protocol Buffers install and Java code</h1>
<h2>1. Build and install Protocol buffers</h2>
<p>./configure<br />
make<br />
make install</p>
<h2>2. Build protobuf Java library</h2>
<p>install maven if not necessary</p>
<p>cd protobuf/java<br />
mvn test<br />
mvn package</p>
<p>get jar from target/protobuf-java-x.x.x.jar</p>
<h2>3. Create .proto file and gen Java code</h2>
<p>tim.proto</p>
<pre>package dns;

message DnsRecord {
required string key = 1;
required string value = 2;
required string first = 3;
required string last = 4;
optional string type = 5 [default = "A"];
optional int32  ttl = 6 [default = 86400];
}

message DnsResponse {
repeated DnsRecord records = 1;
}</pre>
<p>bin/protoc &#8211;java_out . tim.proto</p>
<h2>4. Write Java code</h2>
<pre>// protocol buffer need a builder to create object
Dns.DnsRecord.Builder b = Dns.DnsRecord.newBuilder();
b.setKey("key");
b.setValue("value...");
...
b.builder();

byte[] bytes = dr.toByteArray();
Dns.DnsRecord dr2 = Dns.DnsRecord.parseFrom(bytes);</pre>
<h1>III. Resources</h1>
<p>Thrift: <a href="http://incubator.apache.org/thrift/" target="_blank">http://incubator.apache.org/thrift/</a></p>
<p>Protocol Buffers: <a href="http://code.google.com/apis/protocolbuffers/" target="_blank">http://code.google.com/apis/protocolbuffers/</a></p>
<p>Tim&#8217;s Blog: <a href="http://timyang.net/" target="_self">http://timyang.net/</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-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/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 13.114 ms -->]]></content:encoded>
			<wfw:commentRss>http://timyang.net/programming/thrift-protocol-buffers-java-howto/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>
