<?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; 编程</title>
	<atom:link href="http://timyang.net/category/programming/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>Memcache mutex设计模式</title>
		<link>http://timyang.net/programming/memcache-mutex/</link>
		<comments>http://timyang.net/programming/memcache-mutex/#comments</comments>
		<pubDate>Mon, 26 Jul 2010 15:08:00 +0000</pubDate>
		<dc:creator>Tim</dc:creator>
				<category><![CDATA[编程]]></category>
		<category><![CDATA[cache]]></category>
		<category><![CDATA[memcache]]></category>
		<category><![CDATA[memcached]]></category>
		<category><![CDATA[mutex]]></category>

		<guid isPermaLink="false">http://timyang.net/?p=639</guid>
		<description><![CDATA[周六的S2 Web 2.0技术沙龙上介绍了memcache中使用mutex场景(文后要演讲稿)，有网友对详情感兴趣，简单介绍如下。
场景
Mutex主要用于有大量并发访问并存在cache过期的场合，如

首页top 10, 由数据库加载到memcache缓存n分钟
微博中名人的content cache, 一旦不存在会大量请求不能命中并加载数据库
需要执行多个IO操作生成的数据存在cache中, 比如查询db多次

问题
在大并发的场合，当cache失效时，大量并发同时取不到cache，会同一瞬间去访问db并回设cache，可能会给系统带来潜在的超负荷风险。我们曾经在线上系统出现过类似故障。
解决方法
方法一
在load db之前先add一个mutex key, mutex key add成功之后再去做加载db, 如果add失败则sleep之后重试读取原cache数据。为了防止死锁，mutex key也需要设置过期时间。伪代码如下
(注：下文伪代码仅供了解思路，可能存在bug，欢迎随时指出。)
if (memcache.get(key) == null) {
    // 3 min timeout to avoid mutex holder crash
    if (memcache.add(key_mutex, 3 * 60 * 1000) == true) {
        value = db.get(key);
  [...]]]></description>
			<content:encoded><![CDATA[<p>周六的S2 <a href="http://www.s2forum.org/1/topic/">Web 2.0技术沙龙</a>上介绍了memcache中使用mutex场景(文后要演讲稿)，有网友对详情感兴趣，简单介绍如下。</p>
<h3>场景</h3>
<p>Mutex主要用于有大量并发访问并存在cache过期的场合，如</p>
<ul>
<li>首页top 10, 由数据库加载到memcache缓存n分钟</li>
<li>微博中名人的content cache, 一旦不存在会大量请求不能命中并加载数据库</li>
<li>需要执行多个IO操作生成的数据存在cache中, 比如查询db多次</li>
</ul>
<h3>问题</h3>
<p>在大并发的场合，当cache失效时，大量并发同时取不到cache，会同一瞬间去访问db并回设cache，可能会给系统带来潜在的超负荷风险。<strong>我们曾经在线上系统出现过类似故障</strong>。</p>
<h3>解决方法</h3>
<p><strong>方法一</strong><br />
在load db之前先add一个mutex key, mutex key add成功之后再去做加载db, 如果add失败则sleep之后重试读取原cache数据。为了防止死锁，mutex key也需要设置过期时间。伪代码如下<br />
(<em>注：下文伪代码仅供了解思路，可能存在bug，欢迎随时指出。</em>)</p>
<pre>if (memcache.get(key) == null) {
    // 3 min timeout to avoid mutex holder crash
    if (memcache.add(key_mutex, 3 * 60 * 1000) == true) {
        value = db.get(key);
        memcache.set(key, value);
        memcache.delete(key_mutex);
    } else {
        sleep(50);
        retry();
    }
}</pre>
<p><strong>方法二</strong><br />
在value内部设置1个超时值(timeout1), timeout1比实际的memcache timeout(timeout2)小。当从cache读取到timeout1发现它已经过期时候，马上延长timeout1并重新设置到cache。然后再从数据库加载数据并设置到cache中。伪代码如下</p>
<pre>v = memcache.get(key);
if (v == null) {
    if (memcache.add(key_mutex, 3 * 60 * 1000) == true) {
        value = db.get(key);
        memcache.set(key, value);
        memcache.delete(key_mutex);
    } else {
        sleep(50);
        retry();
    }
} else {
    if (v.timeout &lt;= now()) {
        if (memcache.add(key_mutex, 3 * 60 * 1000) == true) {
            // extend the timeout for other threads
            v.timeout += 3 * 60 * 1000;
            memcache.set(key, v, KEY_TIMEOUT * 2);

            // load the latest value from db
            v = db.get(key);
            v.timeout = KEY_TIMEOUT;
            memcache.set(key, value, KEY_TIMEOUT * 2);
            memcache.delete(key_mutex);
        } else {
            sleep(50);
            retry();
        }
    }
}</pre>
<p>相对于方案一<br />
优点：避免cache失效时刻大量请求获取不到mutex并进行sleep<br />
缺点：代码复杂性增大，因此一般场合用方案一也已经足够。</p>
<p>方案二在Memcached FAQ中也有详细介绍 <a href="http://code.google.com/p/memcached/wiki/FAQ#How_to_prevent_clobbering_updates,_stampeding_requests">How to prevent clobbering updates, stampeding requests</a>，并且Brad还介绍了用他另外一个得意的工具 Gearman 来实现单实例设置cache的方法，见 <a href="http://lists.danga.com/pipermail/memcached/2007-July/004858.html">Cache miss stampedes</a>，不过用Gearman来解决就感觉就有点奇技淫巧了。</p>
<p>附：本次Web2.0技术沙龙演讲主题：微博Cache设计谈，需下载请点击演讲稿下menu/download (需登录slideshare)。</p>
<div id="__ss_4842490" style="width: 425px;"><strong><a title="微博cache设计谈" href="http://www.slideshare.net/iso1600/cache-4842490">微博cache设计谈</a></strong><object id="__sse4842490" classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" width="425" height="355" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"><param name="allowFullScreen" value="true" /><param name="allowScriptAccess" value="always" /><param name="src" value="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=s2weibocachearch-100726101949-phpapp02&amp;stripped_title=cache-4842490" /><param name="name" value="__sse4842490" /><param name="allowfullscreen" value="true" /><embed id="__sse4842490" type="application/x-shockwave-flash" width="425" height="355" src="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=s2weibocachearch-100726101949-phpapp02&amp;stripped_title=cache-4842490" name="__sse4842490" allowscriptaccess="always" allowfullscreen="true"></embed></object></p>
<div style="padding: 5px 0 12px;">View more <a href="http://www.slideshare.net/">presentations</a> from <a href="http://www.slideshare.net/iso1600">Tim Y</a>.</div>
</div>
Similar Posts:<ul><li><a href="http://timyang.net/data/memcached-lru-evictions/" rel="bookmark" title="September 7, 2009">Memcached数据被踢(evictions>0)现象分析</a></li>

<li><a href="http://timyang.net/sns/web20-forum/" rel="bookmark" title="June 6, 2010">Web 2.0技术沙龙设想</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/architecture/farmville/" rel="bookmark" title="March 8, 2010">FarmVille(美版开心农场)谈架构:所有模块都是一个可降级的服务</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>
</ul><!-- Similar Posts took 10.808 ms -->]]></content:encoded>
			<wfw:commentRss>http://timyang.net/programming/memcache-mutex/feed/</wfw:commentRss>
		<slash:comments>14</slash:comments>
		</item>
		<item>
		<title>程序员修炼之道-DRY与巧合编程</title>
		<link>http://timyang.net/programming/pragmatic-programmer/</link>
		<comments>http://timyang.net/programming/pragmatic-programmer/#comments</comments>
		<pubDate>Tue, 01 Jun 2010 01:56:24 +0000</pubDate>
		<dc:creator>Tim</dc:creator>
				<category><![CDATA[编程]]></category>
		<category><![CDATA[coincidence]]></category>
		<category><![CDATA[DRY]]></category>

		<guid isPermaLink="false">http://timyang.net/?p=614</guid>
		<description><![CDATA[DRY(Don&#8217;t Repeat Yourself)是架构设计中经常用到的一句话，这一原则应用非常广泛，在程序设计中同样会用到，不少代码或许不知不觉中违反了这一定义，如《程序员修炼之道》一书中就有如下一题，重构下面一段代码
if (state == TEXAS) {
        rate = TX_RATE;
        amt = base * TX_RATE;
        calc = 2 * basis(amt) + extra(amt) * 1.05;
} else if ((state == OHIO &#124;&#124; (state == MAINE)) {
 [...]]]></description>
			<content:encoded><![CDATA[<p>DRY(Don&#8217;t Repeat Yourself)是架构设计中经常用到的一句话，这一原则应用非常广泛，在程序设计中同样会用到，不少代码或许不知不觉中违反了这一定义，如《程序员修炼之道》一书中就有如下一题，重构下面一段代码</p>
<pre>if (state == TEXAS) {
        rate = TX_RATE;
        amt = base * TX_RATE;
        calc = 2 * basis(amt) + extra(amt) * 1.05;
} else if ((state == OHIO || (state == MAINE)) {
        rate = ((state == OHIO) ? OH_RATE : ME_RATE);
        amt = base * rate;
        calc = 2 * basis(amt) + extra(amt) * 1.05;
        if (state == OHIO)
                points = 2;
} else {
        rate = 1;
        amt = base;
        calc = 2 * basis(amt) + extra(amt) * 1.05;
}</pre>
<p>可能很多人读此代码都有似曾相识之感，不错，我们身边不少程序员就是如此编程的。这段代码就是由于太多Repeat造成罗嗦难懂，结构复杂，维护困难。大家可能都会迅速想到两点重构方法<br />
1. amt, calc 可以移出来<br />
2. 第2个if可以拆分</p>
<p>但是这样就完美了吗？4个if/else是否让人闻到一股不对劲的气味？这段程序是否还是传统结构化编程思维？if条件中state再增多程序会怎样？因此虽然是一段很短的代码，但是重构优化实际是无止境的。</p>
<p><a href="http://timyang.net/blog/wp-content/uploads/2010/06/pragmatic-programmer.jpg"><img class="alignnone size-full wp-image-615" title="pragmatic programmer" src="http://timyang.net/blog/wp-content/uploads/2010/06/pragmatic-programmer.jpg" alt="" width="315" height="420" /></a></p>
<p>再谈巧合编程(Don&#8217;t Programmer by Coincidence)，在很多项目中其实也很常见，巧合编程就是有问题的代码在开发过程中恰好能运行通过，但是运行在别的环境很容易就出问题，比如下面的C++代码</p>
<pre>        a = 2;
        b = 3;
        if (a + b != 5) exit(1);</pre>
<p>什么情况会exit(1)?</p>
<blockquote><p>传统智慧认为，项目一旦进入编码阶段，工作主要就是机械的把设计转换成可执行语句。这种态度是许多程序低效、不可维护的最大原因。<br />
⋯<br />
我们大多数人都能够几乎自动地驾驶汽车，我们不用明确的命令我们的脚踩刹车，或是命令手动方向盘，我们只是想“减速并右转”。但是，可靠的司机会不断查看周围的情况，检查潜在的问题，并且让自己在万一发生意外时处在有利的位置上。编码也是这样。</p></blockquote>
<p>因此开发过程质量问题非常重要, 有经验的程序员懂得如何避开前进过程中的各种雷区。Code review就是在你的驾驶过程中，由另外一名有经验的驾驶员坐在副驾的座位上，帮你纠正各种危险的驾驶习惯，避免在当时或以后踏入各种已知的雷区。</p>
<p><em>本文读后感已先前在新浪微博发出，收到过几十条转发及评论。微博的内容或许更有灵感并及时，欢迎关注</em><a href="http://t.sina.com.cn/timyang"><em>http://t.sina.com.cn/timyang</em></a></p>
Similar Posts:<ul><li><a href="http://timyang.net/misc/productive-programmer/" rel="bookmark" title="May 25, 2010">做卓有成效的程序员</a></li>

<li><a href="http://timyang.net/architecture/communication-code-review/" rel="bookmark" title="May 22, 2009">多服务器通讯层应该如何设计—一次code review小记</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/programming/mythical-5/" rel="bookmark" title="May 19, 2009">5%的神话(关于开发效率与职业方向)</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 13.963 ms -->]]></content:encoded>
			<wfw:commentRss>http://timyang.net/programming/pragmatic-programmer/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<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 13.406 ms -->]]></content:encoded>
			<wfw:commentRss>http://timyang.net/programming/c-erlang-java-performance/feed/</wfw:commentRss>
		<slash:comments>64</slash:comments>
		</item>
		<item>
		<title>关于阙宏宇lighttpd与mod_cache在twitter上的一些讨论</title>
		<link>http://timyang.net/programming/lighttpd-mod_cache-twitter/</link>
		<comments>http://timyang.net/programming/lighttpd-mod_cache-twitter/#comments</comments>
		<pubDate>Sun, 05 Jul 2009 14:52:48 +0000</pubDate>
		<dc:creator>Tim</dc:creator>
				<category><![CDATA[编程]]></category>
		<category><![CDATA[event]]></category>
		<category><![CDATA[lighttpd]]></category>
		<category><![CDATA[mod_cache]]></category>
		<category><![CDATA[thread]]></category>
		<category><![CDATA[twitter]]></category>

		<guid isPermaLink="false">http://timyang.net/?p=306</guid>
		<description><![CDATA[6月28日的beta技术沙龙上阙宏宇介绍了lighttpd与modcache，视频及slide在 http://club.blogbeta.com/76.html，modcache是阙宏宇开发的一个lighttpd module, 它在部分程度上可以替代squid。在活动的介绍上提到
lighttpd是基于事件驱动的高性能web服务器。mod_cache是在lighttpd上运行的缓存插件。lighttpd+mod_cache 搭建的缓存系统，具有配置简单，性能高，在很多大型系统得到了广泛应用。本次活动由mod_cache作者阙宏宇介绍lighttpd的基础知识，讲解 lighttpd高性能的原理，讨论lighttpd的扩展编写方法等高级话题。也将分享mod_cache插件的特点和使用经验。
在看视频的过程中我在twitter上也分享了阙宏宇的一些观点，同时也引起了一些网友的关注及讨论，部分内容摘录如下(下文每行开头的链接是发言人的twitter ID)
xmpp: 刚看到阙宏宇的lighttpd mod_cache视频，他的调优建议把keep-alive设成=0(相当于关掉)，个人不是很认同
xmpp: 阙宏宇称”使用lighttpd+mod_cache比squid快一个数量级，原因是lighttpd用event/file, squid用thread/db“ 视频第41分钟
xmpp: 阙宏宇最后说web server使用多线程是倒退，并拿memcached单线程跑得很好来证明。但是我觉得并不能单纯这么考虑，一是多核CPU被浪费，二是web server(io密集, 慢连接)和cache server特性有区别不能简单相提并论。
SnaiX: @xmpp 我觉得阙宏宇的言论很有问题，首先所谓的event based也是需要较大消耗的，且，squid有n中模式可以选择，包括了所谓的db based files based。
xmpp: @SnaiX 是阿，他的软件对于某些场景可能有意义，但是大部分情况还是没法代替squid的，视频最后Q&#38;A也看到，比如没法实现合并多个相同资源的并发请求等
xmpp: @eishn: &#8220;对于任务的处理, 不可避免会涉及到 multithreading 的问题&#8221; 是 @yingfeng 提到的，在我的理解，“任务”是指为了返回请求，需要消耗cpu及io等待,直至输出内容返回网络这个执行过程
yingfeng: @xmpp 读过POSA II便可知道event based只是解决了acceptor端的问题，对于任务的处理，不可避免会涉及到multithreading的问题
xmpp: @SnaiX: 批评多线程者无非就是批评锁，所以1最极端者就用单线程，2退一步者就线程不共享内存，线程间用消息通讯，3普通多线程通常加锁，因此会带来等待锁(其实Semaphore锁对等待线程没什么开销的)及线程切换开销，因此开发多线程程序只要了解底层原理就没什么恐惧的
xmpp: @eishn 你说的是实现方法是协程吗，我倒很想看到你说的实现方法详细描述。如果是协程，它虽然避免了锁，但还是存在切换开销，而且也不能随时切换，我觉得如要利用多核优势，多线程是大势所趋
alpha86: @xmpp 静态文件的请求可以开keep-alive, 动态请求的话其实keep-alive起不到多大效果。
Joshfeng: @xmpp 我个人觉得keep-alive的设置要看服务器上主要是什么类型的文件
xiaoxiaolu: RT @xmpp: &#8230; 他的调优建议把keep-alive设成=0(相当于关掉)，个人不是很认同//就web而言,我挺认同的
mikespook: RT: @xiaoxiaolu: RT @xmpp: 刚看到&#8230;.调优建议把keep-alive设成=0(相当于关掉)，个人不是很认同//就web而言,我挺认同的// [...]]]></description>
			<content:encoded><![CDATA[<p>6月28日的beta技术沙龙上阙宏宇介绍了<a href="http://www.lighttpd.net/">lighttpd</a>与<a href="http://www.linux.com.cn/modcache/">modcache</a>，视频及slide在 <a href="http://club.blogbeta.com/76.html">http://club.blogbeta.com/76.html</a>，modcache是阙宏宇开发的一个lighttpd module, 它在部分程度上可以替代squid。在活动的介绍上提到</p>
<blockquote><p>lighttpd是基于事件驱动的高性能web服务器。mod_cache是在lighttpd上运行的缓存插件。lighttpd+mod_cache 搭建的缓存系统，具有配置简单，性能高，在很多大型系统得到了广泛应用。本次活动由mod_cache作者阙宏宇介绍lighttpd的基础知识，讲解 lighttpd高性能的原理，讨论lighttpd的扩展编写方法等高级话题。也将分享mod_cache插件的特点和使用经验。</p></blockquote>
<p>在看视频的过程中我在twitter上也分享了阙宏宇的一些观点，同时也引起了一些网友的关注及讨论，部分内容摘录如下(下文每行开头的链接是发言人的twitter ID)</p>
<p><a href="http://twitter.com/xmpp">xmpp</a>: 刚看到阙宏宇的lighttpd mod_cache视频，他的调优建议把keep-alive设成=0(相当于关掉)，个人不是很认同</p>
<p><a href="http://twitter.com/xmpp">xmpp</a>: 阙宏宇称”使用lighttpd+mod_cache比squid快一个数量级，原因是lighttpd用event/file, squid用thread/db“ 视频第41分钟</p>
<p><a href="http://twitter.com/xmpp">xmpp</a>: 阙宏宇最后说web server使用多线程是倒退，并拿memcached单线程跑得很好来证明。但是我觉得并不能单纯这么考虑，一是多核CPU被浪费，二是web server(io密集, 慢连接)和cache server特性有区别不能简单相提并论。</p>
<p><a href="http://twitter.com/SnaiX">SnaiX</a>: @xmpp 我觉得阙宏宇的言论很有问题，首先所谓的event based也是需要较大消耗的，且，squid有n中模式可以选择，包括了所谓的db based files based。</p>
<p><a href="http://twitter.com/xmpp">xmpp</a>: @<a href="http://twitter.com/SnaiX">SnaiX</a> 是阿，他的软件对于某些场景可能有意义，但是大部分情况还是没法代替squid的，视频最后Q&amp;A也看到，比如没法实现合并多个相同资源的并发请求等</p>
<p><a href="http://twitter.com/xmpp">xmpp</a>: @<a href="http://twitter.com/eishn">eishn</a>: &#8220;对于任务的处理, 不可避免会涉及到 multithreading 的问题&#8221; 是 @yingfeng 提到的，在我的理解，“任务”是指为了返回请求，需要消耗cpu及io等待,直至输出内容返回网络这个执行过程</p>
<p><a href="http://twitter.com/yingfeng">yingfeng</a>: @xmpp 读过POSA II便可知道event based只是解决了acceptor端的问题，对于任务的处理，不可避免会涉及到multithreading的问题</p>
<p><a href="http://twitter.com/xmpp">xmpp</a>: @<a href="http://twitter.com/SnaiX">SnaiX</a>: 批评多线程者无非就是批评锁，所以1最极端者就用单线程，2退一步者就线程不共享内存，线程间用消息通讯，3普通多线程通常加锁，因此会带来等待锁(其实Semaphore锁对等待线程没什么开销的)及线程切换开销，因此开发多线程程序只要了解底层原理就没什么恐惧的</p>
<p><a href="http://twitter.com/xmpp">xmpp</a>: @<a href="http://twitter.com/eishn">eishn</a> 你说的是实现方法是协程吗，我倒很想看到你说的实现方法详细描述。如果是协程，它虽然避免了锁，但还是存在切换开销，而且也不能随时切换，我觉得如要利用多核优势，多线程是大势所趋</p>
<p><a href="http://twitter.com/alpha86">alpha86</a>: @xmpp 静态文件的请求可以开keep-alive, 动态请求的话其实keep-alive起不到多大效果。</p>
<p><a href="http://twitter.com/Joshfeng">Joshfeng</a>: @xmpp 我个人觉得keep-alive的设置要看服务器上主要是什么类型的文件</p>
<p><a href="http://twitter.com/xiaoxiaolu">xiaoxiaolu</a>: RT @xmpp: &#8230; 他的调优建议把keep-alive设成=0(相当于关掉)，个人不是很认同//就web而言,我挺认同的</p>
<p><a href="http://twitter.com/mikespook">mikespook</a>: RT: @<a href="http://twitter.com/xiaoxiaolu">xiaoxiaolu</a>: RT @xmpp: 刚看到&#8230;.调优建议把keep-alive设成=0(相当于关掉)，个人不是很认同//就web而言,我挺认同的// 具体情况具体处理，keep-alive 对小文件友好，对高并发不利～</p>
<p><a href="http://twitter.com/rockyzh">rockyzh</a>: @xmpp 同意，现在已经进入多核时代了，当年的squid以高效的单线程著称，现在可得改改了</p>
<p><a href="http://twitter.com/TerryTsui">TerryTsui</a>: RT: @xmpp: 阙宏宇最后说web server使用多线程是倒退，并拿memcached单线程跑得很好来证明。。。 //memcache 也可以是多线程跑啊</p>
<p><a href="http://twitter.com/xiaoxiaolu">xiaoxiaolu</a>: RT @mikespook: RT: @xiaoxiaolu: RT @xmpp:调优建议把keep-alive设成=0，个人不是很认同//我挺认同// 具体情况具体处理，keep-alive 对小文件友好，对高并发不利～//高并发看情况,若跳出率很高,就关掉,省事的话,一律关掉</p>
<p><a href="http://twitter.com/SnaiX">SnaiX</a>: @xmpp 在他视频20分钟左右的位置，提到squid和lighty的比较。提到“能不用线程就不用线程，尤其是几个线程在做同一个事情，用这种事件驱动的模型更好“，我不赞同，这种并发的目的就是用来做同一个事情的。其次就是线程模型和事件驱动一点也不冲突。</p>
<p><a href="http://twitter.com/SnaiX">SnaiX</a>: @xmpp memcached的模型明显是比较简单的模型，为了实现方便而已。所以mc这种东西如果你不适用线程模式或者不对其进行一些特殊优化， 是很难用来吞吐大数据的，因为单线程会使得在write较多数据的时候占用的CPU时间太长，从而直接影响了对别的请求的响应。</p>
<p><a href="http://twitter.com/tangfl">tangfl</a>: @SnaiX @xmpp snaix 应该大力推销一下 csf 模式：前端 event driven，中间任务队列调度，后面线程池处理，完美了。。。</p>
<p><a href="http://twitter.com/eishn">eishn</a>: @xmpp 阙宏宇说webserv使用多线程是倒退，基本赞同。不过其mcachd例子不妥，常规evt负载亦不低。然单线程异步io性能甚于多线程，高并发场合由 是，故多线程非最佳。然实现逻辑，多线程是最易用的，故最佳形式是以模拟多线程写逻辑，而以单线程异步实现，这也是我的做法。</p>
<p><a href="http://twitter.com/jiaojing">jiaojing</a>: RT: @jeffz_cn: rt @xmpp RT: @yingfeng: @xmpp 读过POSA II便可知道event based只是解决了acceptor端的问题，对于任务的处理，&#8230;//多线程也只是用来做cpu时间片的分配,协程也是一个不错的选择.切换代价更 小</p>
<p><a href="http://twitter.com/SnaiX">SnaiX</a>: @xmpp 我认为，如果仅仅是为了避免多线程所造成的程序复杂度上升而在该使用多线程的地方却不使用多线程，是一种无能的表现。譬如说，有言论说：多线程造成你的程序一旦有问题，整个进程就core dump了，所以不稳定。可关键是，你的程序应该有问题么？</p>
<p><a href="http://twitter.com/SnaiX">SnaiX</a>: RT @<a href="http://twitter.com/tangfl">tangfl</a>: @SnaiX @xmpp 其实CSF也没什么可高深的，只是我觉得需要有这么一个东西，这样很多东西就可控了。做技术的，不能整天靠凑合来凑合去的过日子。</p>
<p><a href="http://twitter.com/eishn">eishn</a>: @xmpp stackless python 协程可以做到随时切换, 不过不能达到 erlang 那样的协程级别的多核分配, 尽管可以由用户自己非原生实现。协程虽然还是有切换开销, 但是没有无谓切换, 只在类似 io 等待的场合下才会发生切换, 所以切换次数远小于线程。</p>
<p><a href="http://twitter.com/jiaojing">jiaojing</a>: RT: @eishn: @xmpp stackless python 协程可以做到随时切换, 不过不能达到 erlang 那样的协程级别的多核分配, &#8230;。// erlang的smp也是用多线程(一个核一个线程,ps保证)跑多个scheduler.</p>
<p><a href="http://twitter.com/flierlu">flierlu</a>: 多线程领域也是在不停发展的，近几年 lock-free 和 wait-free 算法逐渐成熟，加上线程局部内存池等等技术，只要设计上不出大问题，肯定能超越多进程</p>
<p><a href="http://twitter.com/zhuzhaoyuan">zhuzhaoyuan</a>: @xmpp: @yingfeng: 读过POSA II便可知道event based只是解决了acceptor端的问题，对于任务的处理，不可避免会涉及到multithreading的问题 || 反对，要看服务类型是IO密集型还是计算密集型的，IO密集型的不需要多线程。</p>
<p><strong>附加说明</strong></p>
<ul>
<li>在Twitter中，@表示reply某人, 类似email中的答复，RT表示retweet,类似email中的转发。</li>
<li>从上面看到，Twitter在讨论上处理线索功能上还是比较弱，需要重复RT原文来串联上下文，很需要类似gmail那样conversation的功能。</li>
<li>我的twitter ID是<a href="http://twitter.com/xmpp">xmpp</a>，欢迎大家follow。</li>
</ul>
Similar Posts:<ul><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-webpy-lighttpd/" rel="bookmark" title="February 26, 2009">python web.py使用flup lighttpd优化过程</a></li>

<li><a href="http://timyang.net/architecture/sohu-im/" rel="bookmark" title="May 19, 2009">搜狐IM</a></li>

<li><a href="http://timyang.net/linux/linux-process/" rel="bookmark" title="May 3, 2009">了解Linux的进程与线程</a></li>

<li><a href="http://timyang.net/data/memcached-lru-evictions/" rel="bookmark" title="September 7, 2009">Memcached数据被踢(evictions>0)现象分析</a></li>
</ul><!-- Similar Posts took 17.952 ms -->]]></content:encoded>
			<wfw:commentRss>http://timyang.net/programming/lighttpd-mod_cache-twitter/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>中国共有多少台服务器-初略估算初窥</title>
		<link>http://timyang.net/programming/fermi-problem/</link>
		<comments>http://timyang.net/programming/fermi-problem/#comments</comments>
		<pubDate>Mon, 25 May 2009 01:13:01 +0000</pubDate>
		<dc:creator>Tim</dc:creator>
				<category><![CDATA[编程]]></category>
		<category><![CDATA[fermi problem]]></category>

		<guid isPermaLink="false">http://timyang.net/?p=225</guid>
		<description><![CDATA[自从看了《编程珠玑》第7章粗略估算之后就养成了一个奇怪的习惯，喜欢去计算身边的数字。比如一个城市共有多少台电梯，中国共有多少座桥梁等。
粗略估算又叫费米近似(Fermi problem)，比如坐广州到深圳的和谐号动车组时候就想，广深线每分钟进入火车站人流量有多大？这个似乎要请专业的调查公司才能得到结果，但实际上每个人几乎都可以算出来，尤其是程序员。

和谐号列车有8个车厢，1号和8号是头等车厢，一般坐不满 ，满员估算50人。除去5号餐车。因此共有5&#215;100+100=600个座位。
15分钟一趟，每天从6点到22点，共发车18*(60/15)=72次
根据观察，广深线平时都有座位，但也不会太空。假如平均坐满70%座位的话，每天单向人流量为 72 * 600 * 70% = 30240 人
每分钟人流量为30240/18/60=28人
进一步考虑，需要几个售票窗口。估算平均每个乘客购票需要15秒，则至少7个窗口才不会引起排队现象。这跟平时观察一致，平时非高峰时刻如果窗口在5个以下会出现排长队现象。

72法则
72法则是会计上的一个经验。假设最初投资金额为100元，复息年利率9%(r%)，利用“72法则”，将72除以9（增长率），得8(y)，即需约8年时间，投资金额滚存至200元（两倍于100元），而准确需时为8.0432年。上面的r和y换成任何数字，只要相乘总数是72, 该法则都成立。
72法则在初略估算中经常要用到，比如上面广深线的例子，假如客流月增长率3%, 则24月之后，广深线客流量会翻一番。(24*3=72)
编程领域估算
服务器编程领域经常面临预先估算，因为在程序开发前实际的场景并不存在。据去年《程序员》杂志介绍，奥运订票网站的瘫痪，是因为每秒请求数超过2200次。假如这个请求数都不能预先估算到的话，应该算是架构设计的失败。
更多有趣例子及深入阅读

中国共有多少台正在运行中的服务器？
你有多少根头发?
成年人体的骨头块数。
孔子的出生年份（公元）

更多有趣的例子可参看美国马里兰大学更多初略估算测试大全(英文)
Similar Posts:Twitter架构图(cache篇)

第一期广州技术沙龙预告

Facebook平台设计(一)

广州技术沙龙设想

利用Gearman来实现远程监控与管理
]]></description>
			<content:encoded><![CDATA[<p>自从看了《<a href="http://www.douban.com/subject/3227098/" target="_blank">编程珠玑</a>》第7章粗略估算之后就养成了一个奇怪的习惯，喜欢去计算身边的数字。比如一个城市共有多少台电梯，中国共有多少座桥梁等。</p>
<p>粗略估算又叫费米近似(<a href="http://en.wikipedia.org/wiki/Fermi_problem" target="_blank">Fermi problem</a>)，比如坐广州到深圳的和谐号动车组时候就想，广深线每分钟进入火车站人流量有多大？这个似乎要请专业的调查公司才能得到结果，但实际上每个人几乎都可以算出来，尤其是程序员。</p>
<ol>
<li>和谐号列车有8个车厢，1号和8号是头等车厢，一般坐不满 ，满员估算50人。除去5号餐车。因此共有5&#215;100+100=600个座位。</li>
<li>15分钟一趟，每天从6点到22点，共发车18*(60/15)=72次</li>
<li>根据观察，广深线平时都有座位，但也不会太空。假如平均坐满70%座位的话，每天单向人流量为 72 * 600 * 70% = 30240 人</li>
<li>每分钟人流量为30240/18/60=28人</li>
<li>进一步考虑，需要几个售票窗口。估算平均每个乘客购票需要15秒，则至少7个窗口才不会引起排队现象。这跟平时观察一致，平时非高峰时刻如果窗口在5个以下会出现排长队现象。</li>
</ol>
<h3>72法则</h3>
<p>72法则是会计上的一个经验。假设最初投资金额为100元，复息年利率9%(r%)，利用“72法则”，将72除以9（增长率），得8(y)，即需约8年时间，投资金额滚存至200元（两倍于100元），而准确需时为8.0432年。上面的r和y换成任何数字，只要相乘总数是72, 该法则都成立。</p>
<p>72法则在初略估算中经常要用到，比如上面广深线的例子，假如客流月增长率3%, 则24月之后，广深线客流量会翻一番。(24*3=72)</p>
<h3>编程领域估算</h3>
<p>服务器编程领域经常面临预先估算，因为在程序开发前实际的场景并不存在。据去年《程序员》杂志介绍，<a href="http://tech.it168.com/a2008/1222/260/000000260841.shtml" target="_blank">奥运订票网站的瘫痪</a>，是因为每秒请求数超过2200次。假如这个请求数都不能预先估算到的话，应该算是架构设计的失败。</p>
<h3>更多有趣例子及深入阅读</h3>
<ul>
<li>中国共有多少台正在运行中的服务器？</li>
<li>你有多少根头发?</li>
<li>成年人体的骨头块数。</li>
<li>孔子的出生年份（公元）</li>
</ul>
<p>更多有趣的例子可参看美国马里兰大学更多<a href="http://www.physics.umd.edu/perg/fermi/fermi.htm" target="_blank">初略估算测试大全</a>(英文)</p>
Similar Posts:<ul><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/tech/guangzhou-salon-guid/" rel="bookmark" title="August 3, 2009">第一期广州技术沙龙预告</a></li>

<li><a href="http://timyang.net/sns/facebook-platform-f8-07/" rel="bookmark" title="June 10, 2009">Facebook平台设计(一)</a></li>

<li><a href="http://timyang.net/tech/guangzhou-salon/" rel="bookmark" title="July 15, 2009">广州技术沙龙设想</a></li>

<li><a href="http://timyang.net/linux/gearman-monitor/" rel="bookmark" title="August 26, 2009">利用Gearman来实现远程监控与管理</a></li>
</ul><!-- Similar Posts took 9.244 ms -->]]></content:encoded>
			<wfw:commentRss>http://timyang.net/programming/fermi-problem/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>5%的神话(关于开发效率与职业方向)</title>
		<link>http://timyang.net/programming/mythical-5/</link>
		<comments>http://timyang.net/programming/mythical-5/#comments</comments>
		<pubDate>Tue, 19 May 2009 05:15:11 +0000</pubDate>
		<dc:creator>Tim</dc:creator>
				<category><![CDATA[编程]]></category>
		<category><![CDATA[mythical]]></category>

		<guid isPermaLink="false">http://timyang.net/?p=172</guid>
		<description><![CDATA[Bruce Eckel(Thinking in Java/C++作者) 在他的 5%的神话 (Mythical 5%) 中提到：
5%的程序员开发效率是其他95%程序员的20倍 
(5% of programmers are 20x more productive than the other 95%)
按照80-20法则,80%的程序员几乎不看书,不读Blog,不参加技术会议，不持续学习。这些人也可能会进入大公司，他们日复一日的做着重复的 工作。另外20%则在专业方面比较主动，他们喜欢阅读，喜欢学习，喜欢参加技术活动。这20%当中又会有80%的人可能不会特别成功，他们仍然走在通往成 功的路上奋斗。剩下20%，也就是总数的5%的开发人员具备20倍的开发效率。
那如何成为这5%中的一员呢
Bruce Eckel 的观点：阅读，分析，总结，实践
这5%的人会习惯经常阅读新技术，并喜欢参与各种有潜在价值的新概念的实践，他们会有非常有选择性的参与会议，大部分时间都花在有效率的事情上，将事情做成。
要想比别人效率高出20%，则需要在各个方面达到平衡，而不单只是能将事情搞定那么简单，因此你要使用最好的工具，最优秀的技术，并尽最大的努力。平衡点并 不是从明显的事物上就可以轻松获得，或者是被人告知的经验，或者是大众化的经验。它需要自己摸索并发现事物背后的规律，需要自己去总结并发现。
比如我们通常对各种编程语言优缺点熟记于心，我们通常可以脱口而出比如erlang适合大并发场合等等。但是大部分人不会意识到很多场合语言并不重要。
因此如果你要成为那5你必须持之以恒的坚持学习，多学习编程是有好处的，但是仅仅局限于了解编程是不够的，比如类似以下经验：

代码被阅读的时间比写代码的时间要长，如果你的代码不能被人理解，则没人会去改善或者修改其中的bug
Code review是最有成效的改善软件缺陷的方法，但在我们却经常“没有时间来考虑它”

所以除了精通编程之外，最好多看一些编程方法与协作的书，如并不传授编程技巧的《代码大全》之类的书。
Jeff Atwood (Coding Horror) 的观点：技术博客重要性
当然也有持不同观点者，如Jeff Atwood(coding horror作者)则认为经常分享自己的技术体会比coding更重要，能写的人才能成为那5%。他曾经横穿北美，从美国西岸San Francisco到加拿大的东岸Montreal去给一个大学的学生讲技术Blog的重要性。他在这篇Is Writing More Important than Programming(ppt, 3mb)演讲中提到：
大部分我景仰的程序员都是通过其blog让我景仰，而不是他的代码
……大部分不写blog程序员的理由有：太忙；写了也没人看；没有合适内容可写；觉得自己不善长表达等。
Jeff Atwood大部分观点我是深表赞同的，可喜的是身边乐于分享的越来越多。比如新浪开发者博客今年2月才开张，现在已经有100多篇高质量文章了。
另外我很敬佩的TopLanguage创建者刘未鹏也写过一篇很有名的为什么你应该（从现在开始就）写博客，想必很多朋友都看过。
其他观点
国内曾翻译过Erlang程序设计的Trustno1则认为这5%的人必须是钻研paper的人, 而只是看看rss，热衷于参加各种技术会议，搞搞各种可替代性很强的技术的人是不够格的，他在某帖子中提到：
很简单的两个标准.
标准一,你看到一个问题的第一感觉&#8221;这个事情不学3-4年数学算法光靠捣鼓捣鼓API设计模式肯定搞不定”
案例一,老板让你做一个从视频里识别出人脸的程序.
标准二,但凡性能Critial又没有现成方案的东西.
案例二,老板让你做一个实时的全局照明渲染引擎.
原讨论在这里 http://www.javaeye.com/topic/380651 其中一些观点也是有争议的，不过话题已经被锁定不让讨论了;)
总结
想必看了上面这一系列，你对怎样成为那5%已有自己的见解了。你要的答案或许不在这篇文章里，因为Bruce Eckel提到，大部分成为5%的人的经验是只可意会，不可言传的。
Similar Posts:为什么优秀开发者进入Google后就不参与开源了

程序员修炼之道-DRY与巧合编程

做卓有成效的程序员

2010年技术实践计划

中国共有多少台服务器-初略估算初窥
]]></description>
			<content:encoded><![CDATA[<p><span class="ts">Bruce Eckel(Thinking in Java/C++作者) 在他的 <a href="http://www.artima.com/weblogs/viewpost.jsp?thread=221622" target="_blank">5%的神话</a> (Mythical 5%) 中提到：</span></p>
<h3><span class="ts">5%的程序员开发效率是其他95%程序员的20倍 </span></h3>
<h3><span class="ts">(5% of programmers are 20x more productive than the other 95%)</span></h3>
<p>按照80-20法则,80%的程序员几乎不看书,不读Blog,不参加技术会议，不持续学习。这些人也可能会进入大公司，他们日复一日的做着重复的 工作。另外20%则在专业方面比较主动，他们喜欢阅读，喜欢学习，喜欢参加技术活动。这20%当中又会有80%的人可能不会特别成功，他们仍然走在通往成 功的路上奋斗。剩下20%，也就是总数的5%的开发人员具备20倍的开发效率。</p>
<p>那如何成为这5%中的一员呢</p>
<h3>Bruce Eckel 的观点：阅读，分析，总结，实践</h3>
<p>这5%的人会习惯经常阅读新技术，并喜欢参与各种有潜在价值的新概念的实践，他们会有非常有选择性的参与会议，大部分时间都花在有效率的事情上，将事情做成。</p>
<p>要想比别人效率高出20%，则需要在各个方面达到平衡，而不单只是能将事情搞定那么简单，因此你要使用最好的工具，最优秀的技术，并尽最大的努力。平衡点并 不是从明显的事物上就可以轻松获得，或者是被人告知的经验，或者是大众化的经验。它需要自己摸索并发现事物背后的规律，需要自己去总结并发现。</p>
<p>比如我们通常对各种编程语言优缺点熟记于心，我们通常可以脱口而出比如erlang适合大并发场合等等。但是大部分人不会意识到很多场合语言并不重要。</p>
<p>因此如果你要成为那5你必须持之以恒的坚持学习，多学习编程是有好处的，但是仅仅局限于了解编程是不够的，比如类似以下经验：</p>
<ul>
<li>代码被阅读的时间比写代码的时间要长，如果你的代码不能被人理解，则没人会去改善或者修改其中的bug</li>
<li>Code review是最有成效的改善软件缺陷的方法，但在我们却经常“没有时间来考虑它”</li>
</ul>
<p>所以除了精通编程之外，最好多看一些编程方法与协作的书，如并不传授编程技巧的《<a href="http://www.douban.com/subject/1477390/" target="_blank">代码大全</a>》之类的书。</p>
<h3>Jeff Atwood (Coding Horror) 的观点：技术博客重要性</h3>
<p>当然也有持不同观点者，如Jeff Atwood(coding horror作者)则认为经常分享自己的技术体会比coding更重要，能写的人才能成为那5%。他曾经横穿北美，从美国西岸San Francisco到加拿大的东岸Montreal去给一个大学的学生讲技术Blog的重要性。他在这篇<a href="http://www.codinghorror.com/blog/files/cusec-2008-presentation-jeff-atwood.zip">Is Writing More Important than Programming</a>(ppt, 3mb)演讲中提到：</p>
<blockquote><p><strong>大部分我景仰的程序员都是通过其blog让我景仰，而不是他的代码</strong></p>
<p>……大部分不写blog程序员的理由有：太忙；写了也没人看；没有合适内容可写；觉得自己不善长表达等。</p></blockquote>
<p>Jeff Atwood大部分观点我是深表赞同的，可喜的是身边乐于分享的越来越多。比如<a href="http://blog.developers.api.sina.com.cn/" target="_blank">新浪开发者博客</a>今年2月才开张，现在已经有100多篇高质量文章了。</p>
<p>另外我很敬佩的<a href="https://groups.google.com/group/pongba" target="_blank">TopLanguage</a>创建者刘未鹏也写过一篇很有名的<a href="http://mindhacks.cn/2009/02/15/why-you-should-start-blogging-now/" target="_blank">为什么你应该（从现在开始就）写博客</a>，想必很多朋友都看过。</p>
<h3>其他观点</h3>
<p>国内曾翻译过<a href="http://www.douban.com/subject/3260311/" target="_blank">Erlang程序设计</a>的Trustno1则认为这5%的人必须是钻研paper的人, 而只是看看rss，热衷于参加各种技术会议，搞搞各种可替代性很强的技术的人是不够格的，他在某帖子中提到：</p>
<blockquote><p>很简单的两个标准.<br />
标准一,你看到一个问题的第一感觉&#8221;这个事情不学3-4年数学算法光靠捣鼓捣鼓API设计模式肯定搞不定”<br />
案例一,老板让你做一个从视频里识别出人脸的程序.<br />
标准二,但凡性能Critial又没有现成方案的东西.<br />
案例二,老板让你做一个实时的全局照明渲染引擎.</p></blockquote>
<p>原讨论在这里 <a href="http://www.javaeye.com/topic/380651" target="_blank">http://www.javaeye.com/topic/380651</a> 其中一些观点也是有争议的，不过话题已经被锁定不让讨论了;)</p>
<h3>总结</h3>
<p>想必看了上面这一系列，你对怎样成为那5%已有自己的见解了。你要的答案或许不在这篇文章里，因为Bruce Eckel提到，大部分成为5%的人的经验是只可意会，不可言传的。</p>
Similar Posts:<ul><li><a href="http://timyang.net/google/open-source/" rel="bookmark" title="April 7, 2010">为什么优秀开发者进入Google后就不参与开源了</a></li>

<li><a href="http://timyang.net/programming/pragmatic-programmer/" rel="bookmark" title="June 1, 2010">程序员修炼之道-DRY与巧合编程</a></li>

<li><a href="http://timyang.net/misc/productive-programmer/" rel="bookmark" title="May 25, 2010">做卓有成效的程序员</a></li>

<li><a href="http://timyang.net/misc/2010-tech-plan/" rel="bookmark" title="December 28, 2009">2010年技术实践计划</a></li>

<li><a href="http://timyang.net/programming/fermi-problem/" rel="bookmark" title="May 25, 2009">中国共有多少台服务器-初略估算初窥</a></li>
</ul><!-- Similar Posts took 12.111 ms -->]]></content:encoded>
			<wfw:commentRss>http://timyang.net/programming/mythical-5/feed/</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
		<item>
		<title>了解Linux的锁与同步</title>
		<link>http://timyang.net/programming/linux-synchronization-lock/</link>
		<comments>http://timyang.net/programming/linux-synchronization-lock/#comments</comments>
		<pubDate>Sun, 10 May 2009 14:54:08 +0000</pubDate>
		<dc:creator>Tim</dc:creator>
				<category><![CDATA[编程]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[lock]]></category>
		<category><![CDATA[synchronization]]></category>

		<guid isPermaLink="false">http://timyang.net/?p=150</guid>
		<description><![CDATA[上周看了Linux的进程与线程，对操作系统的底层有了更进一步的一些了解。我同时用Linux内核设计与实现和Solaris内核结构两本书对比着看，这样更容易产生对比和引发思考。现代操作系统很多思路都是相同的，比如抢占式的多线程及内核、虚拟内存管理等方面。但另外一方面还是有很多差异。在了解锁和同步之前，原子操作是所有一切底层实现的基础。
原子操作Atomic
通常操作系统和硬件都提供特性，可以对一个字节进行原子操作的的读写，并且通常在此基础上来实现更高级的锁特性。

atomic_t结构

原子操作通常针对int或bit类型的数据，但是Linux并不能直接对int进行原子操作，而只能通过atomic_t的数据结构来进行。目前了解到的原因有两个。
一是在老的Linux版本，atomic_t实际只有24位长，低8位用来做锁，如下图所示。这是由于Linux是一个跨平台的实现，可以运行在多种 CPU上，有些类型的CPU比如SPARC并没有原生的atomic指令支持，所以只能在32位int使用8位来做同步锁，避免多个线程同时访问。(最新版SPARC实现已经突破此限制)

另外一个原因是避免atomic_t传递到程序其他地方进行操作修改等。强制使用atomic_t，则避免被不恰当的误用。
atomic_t my_counter = ATOMIC_INIT(0);
val = atomic_read( &#38;my_counter );
atomic_add( 1, &#38;my_counter );
atomic_inc( &#38;my_counter );
atomic_sub( 1, &#38;my_counter );
atomic_dec( &#38;my_counter );

原子操作硬件上的实现

Solaris的实现是基于test-and-set的指令，并且该指令为原子操作。比如Solaris的实现在SPARC上是基于ldstub和cas指令，在x86上用的是cmpxchg指令。但是Linux似乎直接用的add指令。
OpenSolaris i386的实现
	movl	4(%esp), %edx	/ %edx = target address
	movl	(%edx), %eax	/ %eax = old value
1:
	leal	1(%eax), %ecx	/ %ecx = new value
	lock
	cmpxchgl %ecx, (%edx)	/ try to stick it in
	jne	1b
	movl	%ecx, %eax	/ return new value
	ret
在Linux源代码asm_i386/atomic.h中
/**
 * atomic_add - add integer to atomic variable
 * [...]]]></description>
			<content:encoded><![CDATA[<p>上周看了<a href="http://timyang.net/linux/linux-process/">Linux的进程与线程</a>，对操作系统的底层有了更进一步的一些了解。我同时用<a href="http://www.douban.com/subject/1446021/" target="_blank">Linux内核设计与实现</a>和<a href="http://www.douban.com/subject/2161545/" target="_blank">Solaris内核结构</a>两本书对比着看，这样更容易产生对比和引发思考。现代操作系统很多思路都是相同的，比如抢占式的多线程及内核、虚拟内存管理等方面。但另外一方面还是有很多差异。在了解锁和同步之前，原子操作是所有一切底层实现的基础。</p>
<h1>原子操作Atomic</h1>
<p>通常操作系统和硬件都提供特性，可以对一个字节进行原子操作的的读写，并且通常在此基础上来实现更高级的锁特性。</p>
<ul>
<li>atomic_t结构</li>
</ul>
<p>原子操作通常针对int或bit类型的数据，但是Linux并不能直接对int进行原子操作，而只能通过atomic_t的数据结构来进行。目前了解到的原因有两个。</p>
<p>一是在老的Linux版本，atomic_t实际只有24位长，低8位用来做锁，如下图所示。这是由于Linux是一个跨平台的实现，可以运行在多种 CPU上，有些类型的CPU比如SPARC并没有原生的atomic指令支持，所以只能在32位int使用8位来做同步锁，避免多个线程同时访问。(最新版SPARC实现已经突破此限制)</p>
<p><img src="http://timyang.net/blog/wp-content/uploads/2009/05/atomic_t.gif" alt="atomic_t" width="300" height="102" /></p>
<p>另外一个原因是避免atomic_t传递到程序其他地方进行操作修改等。强制使用atomic_t，则避免被不恰当的误用。</p>
<pre>atomic_t my_counter = ATOMIC_INIT(0);
val = atomic_read( &amp;my_counter );
atomic_add( 1, &amp;my_counter );
atomic_inc( &amp;my_counter );
atomic_sub( 1, &amp;my_counter );
atomic_dec( &amp;my_counter );</pre>
<ul>
<li>原子操作硬件上的实现</li>
</ul>
<p>Solaris的实现是基于test-and-set的指令，并且该指令为原子操作。比如Solaris的实现在SPARC上是基于ldstub和cas指令，在x86上用的是cmpxchg指令。但是Linux似乎直接用的add指令。</p>
<p>OpenSolaris i386的实现</p>
<pre>	movl	4(%esp), %edx	/ %edx = target address
	movl	(%edx), %eax	/ %eax = old value
1:
	leal	1(%eax), %ecx	/ %ecx = new value
	lock
	cmpxchgl %ecx, (%edx)	/ try to stick it in
	jne	1b
	movl	%ecx, %eax	/ return new value
	ret</pre>
<p>在Linux源代码asm_i386/atomic.h中</p>
<pre><span class="stx-comment"><span id="l45">/**
</span><span id="l46"> * atomic_add - add integer to atomic variable
</span><span id="l47"> * @i: integer value to add
</span><span id="l48"> * @v: pointer of type atomic_t
</span><span id="l49"> *
</span><span id="l50"> * Atomically adds @i to @v.  Note that the guaranteed useful range
</span><span id="l51"> * of an atomic_t is only 24 bits.
</span></span><span id="l52"><span class="stx-comment"> */</span>
</span><span id="l53"><span class="stx-keyword">static</span> __inline__ <span class="stx-keyword">void</span> atomic_add(<span class="stx-keyword">int</span> i, atomic_t *v)
</span><span id="l54">{
</span><span id="l55">        __asm__ __volatile__(
</span><span id="l56">                LOCK <span class="stx-string">"addl %1,%0"</span>
</span><span id="l57">                :<span class="stx-string">"=m"</span> (v-&gt;counter)
</span><span id="l58">                :<span class="stx-string">"ir"</span> (i), <span class="stx-string">"m"</span> (v-&gt;counter));
</span><span id="l59">}
</span></pre>
<h1>锁的类型</h1>
<ul>
<li>Spinlocks自旋锁</li>
</ul>
<p>如果锁被占用，尝试获取锁的线程进入busy-wait状态，即CPU不停的循环检查锁是否可用。自旋锁适合占用锁非常短的场合，避免等待锁的线程sleep而带来的CPU两个context switch的开销。</p>
<ul>
<li>Semaphores信号量</li>
</ul>
<p>如果锁被占用，尝试获取锁的线程进入sleep状态，CPU切换到别的线程。当锁释放之后，系统会自动唤醒sleep的线程。信号量适合对锁占用较长时间的场合。</p>
<ul>
<li>Adaptive locks自适应锁</li>
</ul>
<p>顾名思义，自适应锁就是上面两种的结合。当线程尝试申请锁，会自动根据拥有锁的线程繁忙或sleep来选择是busy wait还是sleep。这种锁只有Solaris内核提供，Linux上未见有相关描述。</p>
<p>几种锁的性能比较(Windows操作系统下，第一种类似atomic_inc, 2,3类似spinlock, 4,5类似semaphore)</p>
<p><img class="alignnone" title="Relative cost for different locking mechanisms" src="http://software.intel.com/file/7357" alt="" width="423" height="361" /></p>
<p>(图片来源：<a href="http://software.intel.com/en-us/articles/is-the-free-lunch-really-over-scalability-in-manycore-systems-part-2-using-locks-efficiently/" target="_blank">Intel Software Network</a>)</p>
<h1>Java synchronization</h1>
<p>再理论联系实际一下，看Java中的锁底层如何实现的。这篇<a href="http://www.blogjava.net/security/archive/2009/02/16/jvm_thin-lock_fat-lock__spin-lock_tasuki-lock.html" target="_blank">关于JVM的Thin Lock, Fat Lock, SPIN Lock与Tasuki Lock</a>中讲到Java synchronization实际上也是一种自适应锁。</p>
<blockquote><p>于是，JVM早期版本的做法是，如果T1, T2，T3，T4&#8230;产生线程竞争，则T1通过CAS获得锁(此时是Thin Lock方式)，如果T1在CAS期间获得锁，则T2，T3进入SPIN状态直到T1释放锁；而第二个获得锁的线程，比如T2，会将锁升级（Inflation）为Fat Lock，于是，以后尝试获得锁的线程都使用Mutex方式获得锁。</p></blockquote>
<p>Java AtomicInteger的实现，似乎和Solaris的实现非常类似，也是一个busy wait的方式</p>
<pre>   /**
     * Atomically increments by one the current value.
     *
     * @return the updated value
     */
    public final int incrementAndGet() {
        for (;;) {
            int current = get();
            int next = current + 1;
            if (compareAndSet(current, next))
                return next;
        }
    }

    /**
     * Atomically sets the value to the given updated value
     * if the current value {@code ==} the expected value.
     *
     * @param expect the expected value
     * @param update the new value
     * @return true if successful. False return indicates that
     * the actual value was not equal to the expected value.
     */
    public final boolean compareAndSet(int expect, int update) {
        // unsafe.compareAndSwapInt是用本地代码实现
        return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
    }</pre>
<h1>Solaris</h1>
<p>感觉OpenSolaris在很多地方要比Linux优秀，Solaris在理论设计和实践上都非常优雅，而Linux内核很多地方似乎更偏工程实践方向一些。另外Solaris用来做学习操作系统更合适，它的mdb几乎无所不能。</p>
<p>我在<a href="http://www.virtualbox.org/" target="_blank">VirtualBox</a>虚拟机上安装了OpenSolaris，非常容易安装，使用这个<a href="http://blogs.sun.com/jkshah/entry/minimal_opensolaris_image_for_virtualbox" target="_blank">Minimal OpenSolaris Appliance OVF image for VirtualBox 2.2</a> 简易方法，安装一个没有gui的版本，大约3分钟以内就可以装好。OpenSolaris安装软件和Ubuntu一样方便，使用 pkg install SUNWxxx 的命令，比如 pkg install SUNWcurl</p>
Similar Posts:<ul><li><a href="http://timyang.net/linux/linux-process/" rel="bookmark" title="May 3, 2009">了解Linux的进程与线程</a></li>

<li><a href="http://timyang.net/linux/linux-timer-tick/" rel="bookmark" title="May 18, 2009">谈Linux内核定时器</a></li>

<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/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/web/nginx-module/" rel="bookmark" title="March 17, 2009">如何写nginx module</a></li>
</ul><!-- Similar Posts took 14.024 ms -->]]></content:encoded>
			<wfw:commentRss>http://timyang.net/programming/linux-synchronization-lock/feed/</wfw:commentRss>
		<slash:comments>4</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.386 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>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 11.505 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 11.772 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>
