<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0">
  <channel>
    <title>达观.平和</title>
    <description></description>
    <link>http://dustin.javaeye.com</link>
    <language>UTF-8</language>
    <copyright>Copyright 2003-2008, JavaEye.com</copyright>
    <docs>http://blogs.law.harvard.edu/tech/rss</docs>
    <generator>JavaEye - 做最棒的软件开发交流社区</generator>
      <item>
        <title>Two extractors couldn't work together</title>
        <author>Dustin</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://dustin.javaeye.com">Dustin</a>&nbsp;
          链接：<a href="http://dustin.javaeye.com/blog/155195" style="color:red;">http://dustin.javaeye.com/blog/155195</a>&nbsp;
          发表时间: 2008年01月12日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <p>Hi,everyone<br />&nbsp; I have enjoyed Scrubyt for days and it worked greatly in most case.However,problems came out when scraped urls from Google and Yahoo&nbsp;at the same time.Here is my code:</p><p>&nbsp;</p><pre name="code" class="ruby">require 'rubygems'
require 'scrubyt'

Scrubyt.logger = Scrubyt::Logger.new
query = 'ruby'
google_data = Scrubyt::Extractor.define do
      fetch 'http://www.google.com/ncr'
      fill_textfield 'q', query
      submit
      
      #retrieve by xpath
      title &quot;/html/body/div/div/div/a&quot; do
        url &quot;href&quot;, :type =&gt; :attribute
      end
    end #end of extrator
 google_file = File.open(&quot;google.xml&quot;, &quot;w&quot;)
 google_data.to_xml.write(google_file, 1)
 google_file.close
 
 yahoo_data = Scrubyt::Extractor.define do
      fetch 'http://search.yahoo.com'
      fill_textfield 'p', query
      submit
      
       #retrieve by xpath
      title &quot;/html/body/div/div/div/div/div/div/div/ol/li/div/h3/a&quot; do
        url &quot;href&quot;, :type =&gt; :attribute
      end
 end #end of extrator
   
 yahoo_file = File.open(&quot;yahoo.xml&quot;, &quot;w&quot;)
 yahoo_data.to_xml.write(yahoo_file, 1)
 yahoo_file.close</pre><p>&nbsp;</p><p>&nbsp;</p><p>Running Environment: Ubuntu 7.04 + Netbeans 6.0 + Scrubyt</p><p>&nbsp;</p><p>google.xml</p><pre name="code" class="xml">&lt;root&gt;
    &lt;title&gt;
      &lt;url&gt;http://www.ruby-lang.org/&lt;/url&gt;
    &lt;/title&gt;
    &lt;title&gt;
      &lt;url&gt;http://www.ruby-lang.org/en/20020101.html&lt;/url&gt;
    &lt;/title&gt;
    ...
&lt;root&gt;
</pre><p>&nbsp;</p><p>&nbsp;</p><p>yahoo.xml</p><pre name="code" class="xml">&lt;root&gt;
    &lt;title&gt;
      &lt;url&gt;http://rds.yahoo.com/_ylt=A0oGklhqbodHe08AchtXNyoA;_ylu=X3oDMTE5MXY5dDllBHNlYwNzcgRwb3MDMQRjb2xvA3NrMQR2dGlkA1lTMTk4XzgyBGwDV1Mx/SIG=11ff2e34s/EXP=1200144362/**http%3a//www.ruby-lang.org/en&lt;/url&gt;
    &lt;/title&gt;
    &lt;title&gt;
      &lt;url&gt;http://rds.yahoo.com/_ylt=A0oGklhqbodHe08AdBtXNyoA;_ylu=X3oDMTE5cHJpN25qBHNlYwNzcgRwb3MDMgRjb2xvA3NrMQR2dGlkA1lTMTk4XzgyBGwDV1Mx/SIG=12aq03736/EXP=1200144362/**http%3a//en.wikipedia.org/wiki/Ruby_programming_language&lt;/url&gt;
    &lt;/title&gt;
       ...
&lt;root&gt;</pre><p>&nbsp;</p><p>If switched the order of two extractors,that's define yahoo extractor fitstly,the result changed: </p><p><br />google.xml</p><pre name="code" class="xml">&lt;root/&gt;</pre><p>&nbsp;</p><p>yahoo.xml</p><pre name="code" class="xml">&lt;root&gt;
    &lt;title&gt;
      &lt;url&gt;http://www.ruby-lang.org/en&lt;/url&gt;
    &lt;/title&gt;
    &lt;title&gt;
      &lt;url&gt;http://en.wikipedia.org/wiki/Ruby_programming_language&lt;/url&gt;
    &lt;/title&gt;
    .....
&lt;root&gt; </pre><p>&nbsp;</p><p>It seems the latter extractor will be influenced by the former one. Since xpath&nbsp; I used for Yahoo is longer than Google, the result form Google is empty when&nbsp;defined Yahoo extractor firstly.&nbsp; <br />&nbsp; Why is that and how can I overcome this problem? Thanks in advance.</p>
          <br/>
          <span style="color:red;">
            <a href="http://dustin.javaeye.com/blog/155195#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Sat, 12 Jan 2008 01:32:38 +0800</pubDate>
        <link>http://dustin.javaeye.com/blog/155195</link>
        <guid>http://dustin.javaeye.com/blog/155195</guid>
      </item>
      <item>
        <title>测试策略</title>
        <author>Dustin</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://dustin.javaeye.com">Dustin</a>&nbsp;
          链接：<a href="http://dustin.javaeye.com/blog/152191" style="color:red;">http://dustin.javaeye.com/blog/152191</a>&nbsp;
          发表时间: 2008年01月01日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          问题：  <br />  有一个100层高的大厦，你手中有两个相同的玻璃围棋子。从这个大厦的某一层扔下围棋子就会碎，用你手中的这两个玻璃围棋子，找出一个最优的策略，来得知那个临界层面.<br /><br />参考答案：<br /><br />  One drop allows us to test 1 floor.<br />  <br />  Two drops can test 3 floors: Test the second floor first. If it breaks, test the first floor with the other ball. If not, test the top floor with either ball.<br /><br />  Three drops can test 6 floors: Test the third floor first. If it breaks, test the bottom 2 floors in order with the other ball. If not, test the top 3 floors as described above.<br /><br />  Four drops can test 10 floors: Test the fourth floor first. If it breaks, test the bottom 3 floors in order with the other ball. If not, test the top 6 floors as described above.<br /><br />  N drops allows you to test the number of floors equal to the sum of 1 to n. Fourteen drops can test 105 floors: Test the fourteenth floor first. If it breaks, test the bottom 13 floors in order with the other ball. If not, test the twenty-seventh floor next (14 3), and so on.<br /><br />  For any given drop, the number of drops you’ll need after that should be the same if that ball breaks or not (or sometimes they are off by 1 if your total is not an even sum-of-1-to-n).<br /><br />  The optimum test protocol for 100 floors, then, requires a maximum of 14 drops. The next step is to derive a testing strategy that divides the 100 floors using the series 14+13+12+11+10+9+8+7+6+5+4+3+2+1.<br /><br />  The best testing strategy starts with a drop from floor 14; then a drop from floor 27 (14+13); then 39 (14+13+12);etc. The full pattern is 14, 27, 39, 50, 60, 69, 77, 84, 90, 95, 99, 100.<br /><br />  In practice, this series sacrifices the first ball to point to an everdecreasing series of possible target floors. A small number of drops using the second ball then identifies the target floor. Simply go back to the previously tested floor and start working up a floor at a time. <br />Eventually,you will determine the floor at which the bowling ball shatters.<br /><br />This is the most efficient testing algorithm.
          <br/>
          <span style="color:red;">
            <a href="http://dustin.javaeye.com/blog/152191#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Tue, 01 Jan 2008 21:25:38 +0800</pubDate>
        <link>http://dustin.javaeye.com/blog/152191</link>
        <guid>http://dustin.javaeye.com/blog/152191</guid>
      </item>
      <item>
        <title>使用Eclipse跟踪JDK代码执行流程</title>
        <author>Dustin</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://dustin.javaeye.com">Dustin</a>&nbsp;
          链接：<a href="http://dustin.javaeye.com/blog/147977" style="color:red;">http://dustin.javaeye.com/blog/147977</a>&nbsp;
          发表时间: 2007年12月13日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <p>
&nbsp;&nbsp;&nbsp; 现在Eclipse的调试功能相当的强大，Breakpoint，Step Over &amp; Step Into相结合就可以很方便地跟踪代码的执行流程，但有时候要跟踪JDK提供的类的时，却会遇到两个问题：<br />
&nbsp;&nbsp;&nbsp; 1、JDK自带的src.zip里源代码并不完整，不能查看相关类的源文件（当然，喜欢的话可以反编译）。譬如，以sun.开头的包就不包含在src.zip这个压缩包中。<br />
&nbsp;&nbsp;&nbsp; 解决办法：下载完<a href="http://www.sun.com/software/communitysource/j2se/java2/download.xml">整的源文件包</a>，调试时附加给Debugger 即可。
</p>
<p>
&nbsp;&nbsp;&nbsp;&nbsp; 2、默认的 rt.jar没有行号信息，虽然有源代码，但是不能设置断点。<br />
&nbsp;&nbsp; 解决办法：下载<a href="http://www.java.net/download/jdk6/6u10/promoted/b08/binaries/jdk-6u10-ea-bin-b08-windows-i586-debug-30_nov_2007.jar">Debug版的JDK</a>，安装以后将其设置为Eclipse的默认JVM即可。
</p>
<p>
&nbsp;&nbsp; JDK源文件很多，类之间关系相当复杂，跟踪过程中往往会迷失在源码的汪洋大海中，这时，设计模式的知识会派上用场，另外，<span style="font-family: Arial"><a href="http://zvikico.typepad.com/problog/2007/11/five-ways-for-t.html">跟踪Java执行的五种方式 </a>也是一份很好的参考。</span>
</p>

          <br/>
          <span style="color:red;">
            <a href="http://dustin.javaeye.com/blog/147977#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Thu, 13 Dec 2007 02:12:24 +0800</pubDate>
        <link>http://dustin.javaeye.com/blog/147977</link>
        <guid>http://dustin.javaeye.com/blog/147977</guid>
      </item>
      <item>
        <title>拥抱Android</title>
        <author>Dustin</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://dustin.javaeye.com">Dustin</a>&nbsp;
          链接：<a href="http://dustin.javaeye.com/blog/141893" style="color:red;">http://dustin.javaeye.com/blog/141893</a>&nbsp;
          发表时间: 2007年11月23日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <p>
&nbsp; 见证一个新事物的诞生，与全世界同步高呼&ldquo;Hello World&rdquo;，憧憬未来无限的可能性，这确实让人兴奋。开放，开源，Google，带给了我太多的期待。11.12发布后，这个机器人吸引着全世界人的目光。<br />
&nbsp;&nbsp; 1、说起Android，不能不提OHA。由Google牵头，30多家重量级企业投身其中，China Mobile赫然在列，更是凭着首写字母的优势，荣列联名成员列表的第一名：）Android是个开发的平台，使用的是Apache V2的Licence，也就是说联盟成员可以随意修改，让其成为自己特有的版本，而且需要强制公开。如果中国移动能够在08年推出Android版的移动&ldquo;心&rdquo;机的话，对于我们而言最具使用价值的无疑就是打着China Mobile牌子的Android，希望这个机器人在中国能够正常运转啦。
</p>
<p>
&nbsp;&nbsp; 2、Android宣称内置应用程序使用的API与提供给开发者的API是一致的，两者功能一致。这，很爽。
</p>
<p>
&nbsp;&nbsp;&nbsp;3、伴随Android的，还有一个开发大赛，花红高达1000万刀，足以让Android社区的开发人员热血沸腾。我猜大赛的初衷可能是鼓励开发人员积极尝试这个全新的平台，踊跃争当Google的&ldquo;测试人员&rdquo;，为正式版本提供反馈和意见。但是&ldquo;利&rdquo;字当头，会不会成为大家交流的一道无形的屏障，使大家讨论的时候变得&ldquo;欲言又止&rdquo;？这其中利弊在group上也有讨论，个人觉得现在大家在论坛上讨论，应用场景很少提及，这其中应该有开发大赛的因素。
</p>
<p>
&nbsp;&nbsp; 4、Android由身为网络巨头的Google提出，强大的网络功能自然是其特色所在和立命之根本。Demo视频上也演示了如何利用Google提供的，如Gmail，Map等服务Mashup自己的应用，但是不知道这些应用在我国的网络条件下的用户体验如何。此外，中国移动一直不甘心像电信那样仅仅是信息高速公路的修路人，它对内容和服务同样虎视眈眈。在这场不对称的较量中，与移动如何博弈，将是每一个梦想在Android上有所作为的人必须考虑的问题。说起无限网络，就想起3G，在哪？什么时候？
</p>
<p>
&nbsp;
</p>
<p>
<span style="font-family: Arial">&nbsp;&nbsp; 5、Android使用Java作为开发语言，但是与JavaME无关。Google在Linux2.6的内核上铺上众多开源代码，再架上一个源于Apache Harmony的Delvik VM，这算是Google在开源上投入热情的回报吧。不过Android上的Java除了在语法上保持一致外，连字节码都保存为.dex文件，不知道这还能不能叫做Java呢？<br />
&nbsp;&nbsp;&nbsp; 既然Delvik下面跑的是Linux，native问题自然就沸沸扬扬的，这也是group上的热点之一，一帮高手也马上拿出了在Android的模拟器上跑C代码的<a href="http://groups.google.com/group/android-developers/browse_thread/thread/dffafba924e3a2e6/52f09cb4dd9687cc?lnk=gst&amp;q=native#52f09cb4dd9687cc">方案</a>。</span>
</p>
<p>
&nbsp; 6、JavaME虽然被踢出局，但本是同根生，不至于水火不容，有人提出了在Android上跑JavaME的<a href="http://groups.google.com/group/android-developers/browse_thread/thread/42aee09bd0c2922c/ccab3c9a52b97e1f?lnk=gst&amp;q=JavaME#ccab3c9a52b97e1f">方案</a>。
</p>

          <br/>
          <span style="color:red;">
            <a href="http://dustin.javaeye.com/blog/141893#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Fri, 23 Nov 2007 02:03:00 +0800</pubDate>
        <link>http://dustin.javaeye.com/blog/141893</link>
        <guid>http://dustin.javaeye.com/blog/141893</guid>
      </item>
      <item>
        <title>Delegation VS Notification</title>
        <author>Dustin</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://dustin.javaeye.com">Dustin</a>&nbsp;
          链接：<a href="http://dustin.javaeye.com/blog/139546" style="color:red;">http://dustin.javaeye.com/blog/139546</a>&nbsp;
          发表时间: 2007年11月09日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          Delegation:<br />
&nbsp;&nbsp;&nbsp; 消息的发送者(sender)告知接收者(receiver)某个事件将要发生，delegate机制使得接收者可以改变发送者的行为。通常发送者和接收者的关系是直接的一对多的关系。<br />
<br />
Notification:<br />
&nbsp;&nbsp; 消息的发送者告知接收者事件已经发生或者将要发送，仅此而已，接收者并不能反过来影响发送者的行为。通常发送者和接收者的关系是间接的多对多关系。<br />
<br />
Reference：<br />
<p><a href="http://www.stepwise.com/Articles/Technical/2000-03-03.01.html"><font size="4" color="#ff0000" face="Arial"></font><font size="4" color="#ff0000" face="Arial"><a> Delegating Authority        - Cocoa Delegation and Notification</a> </font></a></p>
          <br/>
          <span style="color:red;">
            <a href="http://dustin.javaeye.com/blog/139546#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Fri, 09 Nov 2007 20:01:17 +0800</pubDate>
        <link>http://dustin.javaeye.com/blog/139546</link>
        <guid>http://dustin.javaeye.com/blog/139546</guid>
      </item>
      <item>
        <title>The C10K problem</title>
        <author>Dustin</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://dustin.javaeye.com">Dustin</a>&nbsp;
          链接：<a href="http://dustin.javaeye.com/blog/134563" style="color:red;">http://dustin.javaeye.com/blog/134563</a>&nbsp;
          发表时间: 2007年10月22日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <h1>The C10K problem</h1>
<p>
原文链接：<span style="font-family: Arial"><a href="http://www.kegel.com/c10k.html">http://www.kegel.com/c10k.html</a></span>
</p>
<p>
It's time for web servers to handle ten thousand clients simultaneously, don't you think? After all, the web is a big place now. 
</p>
<p>
And computers are big, too. You can buy a 1000MHz machine with 2 gigabytes of RAM and an 1000Mbit/sec Ethernet card for $1200 or so. Let's see - at 20000 clients, that's 50KHz, 100Kbytes, and 50Kbits/sec per client. It shouldn't take any more horsepower than that to take four kilobytes from the disk and send them to the network once a second for each of twenty thousand clients. (That works out to $0.08 per client, by the way. Those $100/client licensing fees some operating systems charge are starting to look a little heavy!) So hardware is no longer the bottleneck. 
</p>
<p>
In 1999 one of the busiest ftp sites, cdrom.com, actually handled 10000 clients simultaneously through a Gigabit Ethernet pipe. As of 2001, that same speed is now <a href="http://www.senteco.com/telecom/ethernet.htm">being offered by several ISPs</a>, who expect it to become increasingly popular with large business customers. 
</p>
<p>
And the thin client model of computing appears to be coming back in style -- this time with the server out on the Internet, serving thousands of clients. 
</p>
<p>
With that in mind, here are a few notes on how to configure operating systems and write code to support thousands of clients. The discussion centers around Unix-like operating systems, as that's my personal area of interest, but Windows is also covered a bit. 
</p>
<h2>Contents</h2>
<ul>
	<li><a href="http://www.kegel.com/c10k.html#top">The C10K problem</a> </li>
	<li><a href="http://www.kegel.com/c10k.html#related">Related Sites</a> </li>
	<li><a href="http://www.kegel.com/c10k.html#books">Book to Read First</a> </li>
	<li><a href="http://www.kegel.com/c10k.html#frameworks">I/O frameworks</a> </li>
	<li><a href="http://www.kegel.com/c10k.html#strategies">I/O Strategies</a>
	<ol>
		<li><a href="http://www.kegel.com/c10k.html#nb">Serve many clients with each thread, and use nonblocking I/O and <strong>level-triggered</strong> readiness notification</a>
		<ul>
			<li><a href="http://www.kegel.com/c10k.html#nb.select">The traditional select()</a> </li>
			<li><a href="http://www.kegel.com/c10k.html#nb.poll">The traditional poll()</a> </li>
			<li><a href="http://www.kegel.com/c10k.html#nb./dev/poll">/dev/poll</a> (Solaris 2.7+) </li>
			<li><a href="http://www.kegel.com/c10k.html#nb.kqueue">kqueue</a> (FreeBSD, NetBSD) </li>
		</ul>
		</li>
		<li><a href="http://www.kegel.com/c10k.html#nb.edge">Serve many clients with each thread, and use nonblocking I/O and readiness <strong>change</strong> notification</a>
		<ul>
			<li><a href="http://www.kegel.com/c10k.html#nb.epoll">epoll</a> (Linux 2.6+) </li>
			<li><a href="http://www.kegel.com/c10k.html#nb.kevent">Polyakov's kevent</a> (Linux 2.6+) </li>
			<li><a href="http://www.kegel.com/c10k.html#nb.newni">Drepper's New Network Interface</a> (proposal for Linux 2.6+) </li>
			<li><a href="http://www.kegel.com/c10k.html#nb.sigio">Realtime Signals</a> (Linux 2.4+) </li>
			<li><a href="http://www.kegel.com/c10k.html#nb.sigfd">Signal-per-fd</a> </li>
			<li><a href="http://www.kegel.com/c10k.html#nb.kqueue">kqueue</a> (FreeBSD, NetBSD) </li>
		</ul>
		</li>
		<li><a href="http://www.kegel.com/c10k.html#aio">Serve many clients with each thread, and use asynchronous I/O and completion notification</a> </li>
		<li><a href="http://www.kegel.com/c10k.html#threaded">Serve one client with each server thread</a>
		<ul>
			<li><a href="http://www.kegel.com/c10k.html#threads.linuxthreads">LinuxThreads</a> (Linux 2.0+) </li>
			<li><a href="http://www.kegel.com/c10k.html#threads.ngpt">NGPT</a> (Linux 2.4+) </li>
			<li><a href="http://www.kegel.com/c10k.html#threads.nptl">NPTL</a> (Linux 2.6, Red Hat 9) </li>
			<li><a href="http://www.kegel.com/c10k.html#threads.freebsd">FreeBSD threading support</a> </li>
			<li><a href="http://www.kegel.com/c10k.html#threads.netbsd">NetBSD threading support</a> </li>
			<li><a href="http://www.kegel.com/c10k.html#threads.solaris">Solaris threading support</a> </li>
			<li><a href="http://www.kegel.com/c10k.html#threads.java">Java threading support in JDK 1.3.x and earlier</a> </li>
			<li><a href="http://www.kegel.com/c10k.html#1:1">Note: 1:1 threading vs. M:N threading</a> </li>
		</ul>
		</li>
		<li><a href="http://www.kegel.com/c10k.html#kio">Build the server code into the kernel</a> </li>
	</ol>
	</li>
	<li><a href="http://www.kegel.com/c10k.html#comments">Comments</a> </li>
	<li><a href="http://www.kegel.com/c10k.html#limits.filehandles">Limits on open filehandles</a> </li>
	<li><a href="http://www.kegel.com/c10k.html#limits.threads">Limits on threads</a> </li>
	<li><a href="http://www.kegel.com/c10k.html#java">Java issues</a> [Updated 27 May 2001] </li>
	<li><a href="http://www.kegel.com/c10k.html#tips">Other tips</a>
	<ul>
		<li><a href="http://www.kegel.com/c10k.html#zerocopy">Zero-Copy</a> </li>
		<li><a href="http://www.kegel.com/c10k.html#sendfile">The sendfile() system call can implement zero-copy networking.</a> </li>
		<li><a href="http://www.kegel.com/c10k.html#writev">Avoid small frames by using writev (or TCP_CORK)</a> </li>
		<li><a href="http://www.kegel.com/c10k.html#nativethreads">Some programs can benefit from using non-Posix threads.</a> </li>
		<li><a href="http://www.kegel.com/c10k.html#caching">Caching your own data can sometimes be a win.</a> </li>
	</ul>
	</li>
	<li><a href="http://www.kegel.com/c10k.html#limits.other">Other limits</a> </li>
	<li><a href="http://www.kegel.com/c10k.html#kernel">Kernel Issues</a> </li>
	<li><a href="http://www.kegel.com/c10k.html#benchmarking">Measuring Server Performance</a> </li>
	<li><a href="http://www.kegel.com/c10k.html#examples">Examples</a>
	<ul>
		<li><a href="http://www.kegel.com/c10k.html#examples.nb.select">Interesting select()-based servers</a> </li>
		<li><a href="http://www.kegel.com/c10k.html#examples.nb./dev/poll">Interesting /dev/poll-based servers</a> </li>
		<li><a href="http://www.kegel.com/c10k.html#examples.nb.kqueue">Interesting kqueue()-based servers</a> </li>
		<li><a href="http://www.kegel.com/c10k.html#examples.nb.sigio">Interesting realtime signal-based servers</a> </li>
		<li><a href="http://www.kegel.com/c10k.html#examples.threaded">Interesting thread-based servers</a> </li>
		<li><a href="http://www.kegel.com/c10k.html#examples.kio">Interesting in-kernel servers</a> </li>
	</ul>
	</li>
	<li><a href="http://www.kegel.com/c10k.html#links">Other interesting links</a> </li>
</ul>
<p>
&nbsp;
</p>
<h2><a name="related" title="related"></a>Related Sites</h2>
In October 2003, Felix von Leitner put together an excellent <a href="http://bulk.fefe.de/scalability/">web page</a> and <a href="http://bulk.fefe.de/scalable-networking.pdf">presentation</a> about network scalability, complete with benchmarks comparing various networking system calls and operating systems. One of his observations is that the 2.6 Linux kernel really does beat the 2.4 kernel, but there are many, many good graphs that will give the OS developers food for thought for some time. (See also the <a href="http://developers.slashdot.org/developers/03/10/19/0130256.shtml?tid=106&amp;tid=130&amp;tid=185&amp;tid=190">Slashdot</a> comments; it'll be interesting to see whether anyone does followup benchmarks improving on Felix's results.)
<h2><a name="books" title="books"></a>Book to Read First</h2>
<p>
If you haven't read it already, go out and get a copy of <a href="http://www.amazon.com/exec/obidos/ASIN/013490012X/">Unix Network Programming : Networking Apis: Sockets and Xti (Volume 1)</a> by the late W. Richard Stevens. It describes many of the I/O strategies and pitfalls related to writing high-performance servers. It even talks about the <a href="http://www.citi.umich.edu/projects/linux-scalability/reports/accept.html">'thundering herd'</a> problem. And while you're at it, go read <a href="http://pl.atyp.us/content/tech/servers.html">Jeff Darcy's notes on high-performance server design</a>. 
</p>
<p>
(Another book which might be more helpful for those who are *using* rather than *writing* a web server is <a href="http://www.amazon.com/gp/product/0596102356">Building Scalable Web Sites</a> by Cal Henderson.) 
</p>
<h3><a name="frameworks" title="frameworks"></a>I/O frameworks</h3>
<p>
Prepackaged libraries are available that abstract some of the techniques presented below, insulating your code from the operating system and making it more portable. 
</p>
<ul>
	<li><a href="http://www.cs.wustl.edu/~schmidt/ACE.html">ACE</a>, a heavyweight C++ I/O framework, contains object-oriented implementations of some of these I/O strategies and many other useful things. In particular, his Reactor is an OO way of doing nonblocking I/O, and Proactor is an OO way of doing asynchronous I/O. </li>
	<li><a href="http://asio.sf.net/">ASIO</a> is an C++ I/O framework which is becoming part of the Boost library. It's like ACE updated for the STL era. </li>
	<li><a href="http://monkey.org/~provos/libevent">libevent</a> is a lightweight C I/O framework by Niels Provos. It supports kqueue and select, and soon will support poll and epoll. It's level-triggered only, I think, which has both good and bad sides. Niels has <a href="http://monkey.org/~provos/libevent/libevent-benchmark.jpg">a nice graph of time to handle one event</a> as a function of the number of connections. It shows kqueue and sys_epoll as clear winners. </li>
	<li>My own attempts at lightweight frameworks (sadly, not kept up to date):
	<ul>
		<li><a href="http://www.kegel.com/dkftpbench/Poller_bench.html">Poller</a> is a lightweight C++ I/O framework that implements a level-triggered readiness API using whatever underlying readiness API you want (poll, select, /dev/poll, kqueue, or sigio). It's useful for <a href="http://www.kegel.com/dkftpbench/Poller_bench.html">benchmarks that compare the performance of the various APIs.</a> This document links to Poller subclasses below to illustrate how each of the readiness APIs can be used. </li>
		<li><a href="http://www.kegel.com/rn/">rn</a> is a lightweight C I/O framework that was my second try after Poller. It's lgpl (so it's easier to use in commercial apps) and C (so it's easier to use in non-C++ apps). It was used in some commercial products. </li>
	</ul>
	</li>
	<li>Matt Welsh wrote <a href="http://www.cs.berkeley.edu/~mdw/papers/events.pdf">a paper</a> in April 2000 about how to balance the use of worker thread and event-driven techniques when building scalable servers. The paper describes part of his Sandstorm I/O framework. </li>
	<li><a href="http://svn.sourceforge.net/viewcvs.cgi/*checkout*/int64/scale/readme.txt">Cory Nelson's Scale! library</a> - an async socket, file, and pipe I/O library for Windows </li>
</ul>
<h2><a name="strategies" title="strategies"></a>I/O Strategies</h2>
Designers of networking software have many options. Here are a few:
<ul>
	<li>Whether and how to issue multiple I/O calls from a single thread
	<ul>
		<li>Don't; use blocking/synchronous calls throughout, and possibly use multiple threads or processes to achieve concurrency </li>
		<li>Use nonblocking calls (e.g. write() on a socket set to O_NONBLOCK) to start I/O, and readiness notification (e.g. poll() or /dev/poll) to know when it's OK to start the next I/O on that channel. Generally only usable with network I/O, not disk I/O. </li>
		<li>Use asynchronous calls (e.g. aio_write()) to start I/O, and completion notification (e.g. signals or completion ports) to know when the I/O finishes. Good for both network and disk I/O. </li>
	</ul>
	</li>
	<li>How to control the code servicing each client
	<ul>
		<li>one process for each client (classic Unix approach, used since 1980 or so) </li>
		<li>one OS-level thread handles many clients; each client is controlled by:
		<ul>
			<li>a user-level thread (e.g. GNU state threads, classic Java with green threads) </li>
			<li>a state machine (a bit esoteric, but popular in some circles; my favorite) </li>
			<li>a continuation (a bit esoteric, but popular in some circles) </li>
		</ul>
		</li>
		<li>one OS-level thread for each client (e.g. classic Java with native threads) </li>
		<li>one OS-level thread for each active client (e.g. Tomcat with apache front end; NT completion ports; thread pools) </li>
	</ul>
	</li>
	<li>Whether to use standard O/S services, or put some code into the kernel (e.g. in a custom driver, kernel module, or VxD) </li>
</ul>
<p>
The following five combinations seem to be popular: 
</p>
<ol>
	<li><a href="http://www.kegel.com/c10k.html#nb">Serve many clients with each thread, and use nonblocking I/O and <strong>level-triggered</strong> readiness notification</a> </li>
	<li><a href="http://www.kegel.com/c10k.html#nb.edge">Serve many clients with each thread, and use nonblocking I/O and readiness <strong>change</strong> notification</a> </li>
	<li><a href="http://www.kegel.com/c10k.html#aio">Serve many clients with each server thread, and use asynchronous I/O</a> </li>
	<li><a href="http://www.kegel.com/c10k.html#threaded">serve one client with each server thread, and use blocking I/O</a> </li>
	<li><a href="http://www.kegel.com/c10k.html#kio">Build the server code into the kernel</a> </li>
</ol>
<h3><a name="nb" title="nb"></a>1. Serve many clients with each thread, and use nonblocking I/O and <strong>level-triggered</strong> readiness notification</h3>
<p>
... set nonblocking mode on all network handles, and use select() or poll() to tell which network handle has data waiting. This is the traditional favorite. With this scheme, the kernel tells you whether a file descriptor is ready, whether or not you've done anything with that file descriptor since the last time the kernel told you about it. (The name 'level triggered' comes from computer hardware design; it's the opposite of <a href="http://www.kegel.com/c10k.html#nb.edge">'edge triggered'</a>. Jonathon Lemon introduced the terms in his <a href="http://people.freebsd.org/~jlemon/papers/kqueue.pdf">BSDCON 2000 paper on kqueue()</a>.) 
</p>
<p>
Note: it's particularly important to remember that readiness notification from the kernel is only a hint; the file descriptor might not be ready anymore when you try to read from it. That's why it's important to use nonblocking mode when using readiness notification. 
</p>
<p>
An important bottleneck in this method is that read() or sendfile() from disk blocks if the page is not in core at the moment; setting nonblocking mode on a disk file handle has no effect. Same thing goes for memory-mapped disk files. The first time a server needs disk I/O, its process blocks, all clients must wait, and that raw nonthreaded performance goes to waste. <br />
This is what asynchronous I/O is for, but on systems that lack AIO, worker threads or processes that do the disk I/O can also get around this bottleneck. One approach is to use memory-mapped files, and if mincore() indicates I/O is needed, ask a worker to do the I/O, and continue handling network traffic. Jef Poskanzer mentions that Pai, Druschel, and Zwaenepoel's 1999 <a href="http://www.cs.rice.edu/~vivek/flash99/">Flash</a> web server uses this trick; they gave a talk at <a href="http://www.usenix.org/events/usenix99/technical.html">Usenix '99</a> on it. It looks like mincore() is available in BSD-derived Unixes like <a href="http://www.freebsd.org/cgi/man.cgi?query=mincore">FreeBSD</a> and Solaris, but is not part of the <a href="http://www.unix-systems.org/">Single Unix Specification</a>. It's available as part of Linux as of kernel 2.3.51, <a href="http://www.citi.umich.edu/projects/citi-netscape/status/mar-apr2000.html">thanks to Chuck Lever</a>. 
</p>
<p>
But <a href="http://marc.theaimsgroup.com/?l=freebsd-hackers&amp;m=106718343317930&amp;w=2">in November 2003 on the freebsd-hackers list, Vivek Pei et al reported</a> very good results using system-wide profiling of their Flash web server to attack bottlenecks. One bottleneck they found was mincore (guess that wasn't such a good idea after all) Another was the fact that sendfile blocks on disk access; they improved performance by introducing a modified sendfile() that return something like EWOULDBLOCK when the disk page it's fetching is not yet in core. (Not sure how you tell the user the page is now resident... seems to me what's really needed here is aio_sendfile().) The end result of their optimizations is a SpecWeb99 score of about 800 on a 1GHZ/1GB FreeBSD box, which is better than anything on file at spec.org. 
</p>
<p>
There are several ways for a single thread to tell which of a set of nonblocking sockets are ready for I/O: 
</p>
<ul>
	<li><a name="nb.select" title="nb.select"></a><strong>The traditional select()</strong> <br />
	Unfortunately, select() is limited to FD_SETSIZE handles. This limit is compiled in to the standard library and user programs. (Some versions of the C library let you raise this limit at user app compile time.)
	<p>
	See <a href="http://www.kegel.com/dkftpbench/doc/Poller_select.html">Poller_select</a> (<a href="http://www.kegel.com/dkftpbench/dkftpbench-0.44/Poller_select.cc">cc</a>, <a href="http://www.kegel.com/dkftpbench/dkftpbench-0.44/Poller_select.h">h</a>) for an example of how to use select() interchangeably with other readiness notification schemes. 
	</p>
	<p>
	&nbsp;
	</p>
	</li>
	<li><a name="nb.poll" title="nb.poll"></a><strong>The traditional poll()</strong> <br />
	There is no hardcoded limit to the number of file descriptors poll() can handle, but it does get slow about a few thousand, since most of the file descriptors are idle at any one time, and scanning through thousands of file descriptors takes time.
	<p>
	Some OS's (e.g. Solaris 8) speed up poll() et al by use of techniques like poll hinting, which was <a href="http://www.humanfactor.com/cgi-bin/cgi-delegate/apache-ML/nh/1999/May/0415.html">implemented and benchmarked by Niels Provos</a> for Linux in 1999. 
	</p>
	<p>
	See <a href="http://www.kegel.com/dkftpbench/doc/Poller_poll.html">Poller_poll</a> (<a href="http://www.kegel.com/dkftpbench/dkftpbench-0.44/Poller_poll.cc">cc</a>, <a href="http://www.kegel.com/dkftpbench/dkftpbench-0.44/Poller_poll.h">h</a>, <a href="http://www.kegel.com/dkftpbench/Poller_bench.html">benchmarks</a>) for an example of how to use poll() interchangeably with other readiness notification schemes. 
	</p>
	<p>
	&nbsp;
	</p>
	</li>
	<li><a name="nb./dev/poll" title="nb./dev/poll"></a><strong>/dev/poll</strong><br />
	This is the recommended poll replacement for Solaris.
	<p>
	The idea behind /dev/poll is to take advantage of the fact that often poll() is called many times with the same arguments. With /dev/poll, you get an open handle to /dev/poll, and tell the OS just once what files you're interested in by writing to that handle; from then on, you just read the set of currently ready file descriptors from that handle. 
	</p>
	<p>
	It appeared quietly in Solaris 7 (<a href="http://sunsolve.sun.com/pub-cgi/retrieve.pl?patchid=106541&amp;collection=fpatches">see patchid 106541</a>) but its first public appearance was in <a href="http://docs.sun.com/ab2/coll.40.6/REFMAN7/@Ab2PageView/55123?Ab2Lang=C&amp;Ab2Enc=iso-8859-1">Solaris 8</a>; <a href="http://www.sun.com/sysadmin/ea/poll.html">according to Sun</a>, at 750 clients, this has 10% of the overhead of poll(). 
	</p>
	<p>
	Various implementations of /dev/poll were tried on Linux, but none of them perform as well as epoll, and were never really completed. /dev/poll use on Linux is not recommended. 
	</p>
	<p>
	See <a href="http://www.kegel.com/dkftpbench/doc/Poller_devpoll.html">Poller_devpoll</a> (<a href="http://www.kegel.com/dkftpbench/dkftpbench-0.44/Poller_devpoll.cc">cc</a>, <a href="http://www.kegel.com/dkftpbench/dkftpbench-0.44/Poller_devpoll.h">h</a> <a href="http://www.kegel.com/dkftpbench/Poller_bench.html">benchmarks</a> ) for an example of how to use /dev/poll interchangeably with many other readiness notification schemes. (Caution - the example is for Linux /dev/poll, might not work right on Solaris.) 
	</p>
	<p>
	&nbsp;
	</p>
	</li>
	<li><strong>kqueue()</strong><br />
	This is the recommended poll replacement for FreeBSD (and, soon, NetBSD).
	<p>
	<a href="http://www.kegel.com/c10k.html#nb.kqueue">See below.</a> kqueue() can specify either edge triggering or level triggering. 
	</p>
	</li>
</ul>
<h3><a name="nb.edge" title="nb.edge"></a>2. Serve many clients with each thread, and use nonblocking I/O and readiness <strong>change</strong> notification</h3>
Readiness change notification (or edge-triggered readiness notification) means you give the kernel a file descriptor, and later, when that descriptor transitions from <em>not ready</em> to <em>ready</em>, the kernel notifies you somehow. It then assumes you know the file descriptor is ready, and will not send any more readiness notifications of that type for that file descriptor until you do something that causes the file descriptor to no longer be ready (e.g. until you receive the EWOULDBLOCK error on a send, recv, or accept call, or a send or recv transfers less than the requested number of bytes).
<p>
When you use readiness change notification, you must be prepared for spurious events, since one common implementation is to signal readiness whenever any packets are received, regardless of whether the file descriptor was already ready. 
</p>
<p>
This is the opposite of &quot;<a href="http://www.kegel.com/c10k.html#nb">level-triggered</a>&quot; readiness notification. It's a bit less forgiving of programming mistakes, since if you miss just one event, the connection that event was for gets stuck forever. Nevertheless, I have found that edge-triggered readiness notification made programming nonblocking clients with OpenSSL easier, so it's worth trying. 
</p>
<p>
<a href="http://www.cs.rice.edu/~druschel/usenix99event.ps.gz">[Banga, Mogul, Drusha '99]</a> described this kind of scheme in 1999. 
</p>
<p>
There are several APIs which let the application retrieve 'file descriptor became ready' notifications: 
</p>
<ul>
	<li><a name="nb.kqueue" title="nb.kqueue"></a><strong>kqueue()</strong> This is the recommended edge-triggered poll replacement for FreeBSD (and, soon, NetBSD).
	<p>
	FreeBSD 4.3 and later, and <a href="http://kerneltrap.org/node.php?id=472">NetBSD-current as of Oct 2002</a>, support a generalized alternative to poll() called <a href="http://www.freebsd.org/cgi/man.cgi?query=kqueue&amp;apropos=0&amp;sektion=0&amp;manpath=FreeBSD+5.0-current&amp;format=html">kqueue()/kevent()</a>; it supports both edge-triggering and level-triggering. (See also <a href="http://people.freebsd.org/~jlemon/">Jonathan Lemon's page</a> and his <a href="http://people.freebsd.org/~jlemon/papers/kqueue.pdf">BSDCon 2000 paper on kqueue()</a>.) 
	</p>
	<p>
	Like /dev/poll, you allocate a listening object, but rather than opening the file /dev/poll, you call kqueue() to allocate one. To change the events you are listening for, or to get the list of current events, you call kevent() on the descriptor returned by kqueue(). It can listen not just for socket readiness, but also for plain file readiness, signals, and even for I/O completion. 
	</p>
	<p>
	<strong>Note:</strong> as of October 2000, the threading library on FreeBSD does not interact well with kqueue(); evidently, when kqueue() blocks, the entire process blocks, not just the calling thread. 
	</p>
	<p>
	See <a href="http://www.kegel.com/dkftpbench/doc/Poller_kqueue.html">Poller_kqueue</a> (<a href="http://www.kegel.com/dkftpbench/dkftpbench-0.44/Poller_kqueue.cc">cc</a>, <a href="http://www.kegel.com/dkftpbench/dkftpbench-0.44/Poller_kqueue.h">h</a>, <a href="http://www.kegel.com/dkftpbench/Poller_bench.html">benchmarks</a>) for an example of how to use kqueue() interchangeably with many other readiness notification schemes. 
	</p>
	<p>
	Examples and libraries using kqueue(): 
	</p>
	<ul>
		<li><a href="http://people.freebsd.org/~dwhite/PyKQueue/">PyKQueue</a> -- a Python binding for kqueue() </li>
		<li><a href="http://www.monkeys.com/kqueue/echo.c">Ronald F. Guilmette's example echo server</a>; see also <a href="http://groups.yahoo.com/group/freebsd-questions/message/223580">his 28 Sept 2000 post on freebsd.questions</a>. </li>
	</ul>
	<p>
	&nbsp;
	</p>
	</li>
	<li><a name="nb.epoll" title="nb.epoll"></a><strong>epoll</strong><br />
	This is the recommended edge-triggered poll replacement for the 2.6 Linux kernel.
	<p>
	On 11 July 2001, Davide Libenzi proposed an alternative to realtime signals; his patch provides what he now calls <a href="http://www.xmailserver.org/linux-patches/nio-improve.html">/dev/epoll www.xmailserver.org/linux-patches/nio-improve.html</a>. This is just like the realtime signal readiness notification, but it coalesces redundant events, and has a more efficient scheme for bulk event retrieval. 
	</p>
	<p>
	Epoll was merged into the 2.5 kernel tree as of 2.5.46 after its interface was changed from a special file in /dev to a system call, sys_epoll. A patch for the older version of epoll is available for the 2.4 kernel. 
	</p>
	<p>
	There was a lengthy debate about <a href="http://marc.theaimsgroup.com/?l=linux-kernel&amp;m=103607925020720&amp;w=2">unifying epoll, aio, and other event sources</a> on the linux-kernel mailing list around Halloween 2002. It may yet happen, but Davide is concentrating on firming up epoll in general first. 
	</p>
	<p>
	&nbsp;
	</p>
	</li>
	<li><a name="nb.kevent" title="nb.kevent"></a>Polyakov's kevent (Linux 2.6+) <a name="kevent" title="kevent"></a>News flash: On 9 Feb 2006, and again on 9 July 2006, Evgeniy Polyakov posted patches which seem to unify epoll and aio; his goal is to support network AIO. See:
	<ul>
		<li><a href="http://lwn.net/Articles/172844/">the LWN article about kevent</a> </li>
		<li><a href="http://lkml.org/lkml/2006/7/9/82">his July announcement</a> </li>
		<li><a href="http://tservice.net.ru/~s0mbre/old/?section=projects&amp;item=kevent">his kevent page</a> </li>
		<li><a href="http://tservice.net.ru/~s0mbre/old/?section=projects&amp;item=naio">his naio page</a> </li>
		<li><a href="http://thread.gmane.org/gmane.linux.network/37595/focus=37673">some recent discussion</a> </li>
	</ul>
	<p>
	&nbsp;
	</p>
	</li>
	<li><a name="nb.newni" title="nb.newni"></a>Drepper's New Network Interface (proposal for Linux 2.6+)<br />
	At OLS 2006, Ulrich Drepper proposed a new high-speed asynchronous networking API. See:
	<ul>
		<li>his paper, &quot;<a href="http://people.redhat.com/drepper/newni.pdf">The Need for Asynchronous, Zero-Copy Network I/O</a>&quot; </li>
		<li><a href="http://people.redhat.com/drepper/newni-slides.pdf">his slides</a> </li>
		<li><a href="http://lwn.net/Articles/192410/">LWN article from July 22</a> </li>
	</ul>
	<p>
	&nbsp;
	</p>
	</li>
	<li><a name="nb.sigio" title="nb.sigio"></a><strong>Realtime Signals</strong><br />
	This is the recommended edge-triggered poll replacement for the 2.4 Linux kernel.
	<p>
	The 2.4 linux kernel can deliver socket readiness events via a particular realtime signal. Here's how to turn this behavior on: 
	</p>
	<pre>
	/* Mask off SIGIO and the signal you want to use. */
	sigemptyset(&amp;sigset);
	sigaddset(&amp;sigset, signum);
	sigaddset(&amp;sigset, SIGIO);
	sigprocmask(SIG_BLOCK, &amp;m_sigset, NULL);
	/* For each file descriptor, invoke F_SETOWN, F_SETSIG, and set O_ASYNC. */
	fcntl(fd, F_SETOWN, (int) getpid());
	fcntl(fd, F_SETSIG, signum);
	flags = fcntl(fd, F_GETFL);
	flags |= O_NONBLOCK|O_ASYNC;
	fcntl(fd, F_SETFL, flags);
	</pre>
	This sends that signal when a normal I/O function like read() or write() completes. To use this, write a normal poll() outer loop, and inside it, after you've handled all the fd's noticed by poll(), you loop calling <a href="http://www.opengroup.org/onlinepubs/007908799/xsh/sigwaitinfo.html">sigwaitinfo()</a>.<br />
	If sigwaitinfo or sigtimedwait returns your realtime signal, siginfo.si_fd and siginfo.si_band give almost the same information as pollfd.fd and pollfd.revents would after a call to poll(), so you handle the i/o, and continue calling sigwaitinfo().<br />
	If sigwaitinfo returns a traditional SIGIO, the signal queue overflowed, so you <a href="http://www.cs.helsinki.fi/linux/linux-kernel/Year-1999/1999-41/0644.html">flush the signal queue by temporarily changing the signal handler to SIG_DFL</a>, and break back to the outer poll() loop. <br />
	<p>
	See <a href="http://www.kegel.com/dkftpbench/doc/Poller_sigio.html">Poller_sigio</a> (<a href="http://www.kegel.com/dkftpbench/dkftpbench-0.44/Poller_sigio.cc">cc</a>, <a href="http://www.kegel.com/dkftpbench/dkftpbench-0.44/Poller_sigio.h">h</a>) for an example of how to use rtsignals interchangeably with many other readiness notification schemes. 
	</p>
	<p>
	See <a href="http://www.kegel.com/c10k.html#phhttpd">Zach Brown's phhttpd</a> for example code that uses this feature directly. (Or don't; phhttpd is a bit hard to figure out...) 
	</p>
	<p>
	[<a href="http://www.citi.umich.edu/techreports/reports/citi-tr-00-7.ps.gz">Provos, Lever, and Tweedie 2000</a>] describes a recent benchmark of phhttpd using a variant of sigtimedwait(), sigtimedwait4(), that lets you retrieve multiple signals with one call. Interestingly, the chief benefit of sigtimedwait4() for them seemed to be it allowed the app to gauge system overload (so it could <a href="http://www.kegel.com/c10k.html#overload">behave appropriately</a>). (Note that poll() provides the same measure of system overload.) 
	</p>
	<p>
	&nbsp;
	</p>
	</li>
	<li><a name="nb.sigfd" title="nb.sigfd"></a><strong>Signal-per-fd</strong><br />
	Chandra and Mosberger proposed a modification to the realtime signal approach called &quot;signal-per-fd&quot; which reduces or eliminates realtime signal queue overflow by coalescing redundant events. It doesn't outperform epoll, though. Their paper ( <a href="http://www.hpl.hp.com/techreports/2000/HPL-2000-174.html">www.hpl.hp.com/techreports/2000/HPL-2000-174.html</a>) compares performance of this scheme with select() and /dev/poll.<br />
	<p>
	<a href="http://boudicca.tux.org/hypermail/linux-kernel/2001week20/1353.html">Vitaly Luban announced a patch implementing this scheme on 18 May 2001</a>; his patch lives at <a href="http://www.luban.org/GPL/gpl.html">www.luban.org/GPL/gpl.html</a>. (Note: as of Sept 2001, there may still be stability problems with this patch under heavy load. <a href="http://www.kegel.com/dkftpbench">dkftpbench</a> at about 4500 users may be able to trigger an oops.) 
	</p>
	<p>
	See <a href="http://www.kegel.com/dkftpbench/doc/Poller_sigfd.html">Poller_sigfd</a> (<a href="http://www.kegel.com/dkftpbench/dkftpbench-0.44/Poller_sigfd.cc">cc</a>, <a href="http://www.kegel.com/dkftpbench/dkftpbench-0.44/Poller_sigfd.h">h</a>) for an example of how to use signal-per-fd interchangeably with many other readiness notification schemes. 
	</p>
	</li>
</ul>
<h3><a name="aio" title="aio"></a>3. Serve many clients with each server thread, and use asynchronous I/O</h3>
<p>
This has not yet become popular in Unix, probably because few operating systems support asynchronous I/O, also possibly because it (like nonblocking I/O) requires rethinking your application. Under standard Unix, asynchronous I/O is provided by <a href="http://www.opengroup.org/onlinepubs/007908799/xsh/realtime.html">the aio_ interface</a> (scroll down from that link to &quot;Asynchronous input and output&quot;), which associates a signal and value with each I/O operation. Signals and their values are queued and delivered efficiently to the user process. This is from the POSIX 1003.1b realtime extensions, and is also in the Single Unix Specification, version 2. 
</p>
<p>
AIO is normally used with edge-triggered completion notification, i.e. a signal is queued when the operation is complete. (It can also be used with level triggered completion notification by calling <a href="http://www.opengroup.org/onlinepubs/007908799/xsh/aio_suspend.html">aio_suspend()</a>, though I suspect few people do this.) 
</p>
<p>
glibc 2.1 and later provide a generic implementation written for standards compliance rather than performance. 
</p>
<p>
Ben LaHaise's implementation for Linux AIO was merged into the main Linux kernel as of 2.5.32. It doesn't use kernel threads, and has a very efficient underlying api, but (as of 2.6.0-test2) doesn't yet support sockets. (There is also an AIO patch for the 2.4 kernels, but the 2.5/2.6 implementation is somewhat different.) More info: 
</p>
<ul>
	<li>The page &quot;<a href="http://lse.sourceforge.net/io/aio.html">Kernel Asynchronous I/O (AIO) Support for Linux</a>&quot; which tries to tie together all info about the 2.6 kernel's implementation of AIO (posted 16 Sept 2003) </li>
	<li><a href="http://www.linuxsymposium.org/2002/view_txt.php?text=abstract&amp;talk=11">Round 3: aio vs /dev/epoll</a> by Benjamin C.R. LaHaise (presented at 2002 OLS) </li>
	<li><a href="http://archive.linuxsymposium.org/ols2003/Proceedings/All-Reprints/Reprint-Pulavarty-OLS2003.pdf">Asynchronous I/O Suport in Linux 2.5</a>, by Bhattacharya, Pratt, Pulaverty, and Morgan, IBM; presented at OLS '2003 </li>
	<li><a href="http://sourceforge.net/docman/display_doc.php?docid=12548&amp;group_id=8875">Design Notes on Asynchronous I/O (aio) for Linux</a> by Suparna Bhattacharya -- compares Ben's AIO with SGI's KAIO and a few other AIO projects </li>
	<li><a href="http://www.kvack.org/~blah/aio/">Linux AIO home page</a> - Ben's preliminary patches, mailing list, etc. </li>
	<li><a href="http://marc.theaimsgroup.com/?l=linux-aio">linux-aio mailing list archives</a> </li>
	<li><a href="http://www.ocfs.org/aio/">libaio-oracle</a> - library implementing standard Posix AIO on top of libaio. <a href="http://marc.theaimsgroup.com/?l=linux-aio&amp;m=105069158425822&amp;w=2">First mentioned by Joel Becker on 18 Apr 2003</a>. </li>
</ul>
Suparna also suggests having a look at the <a href="http://www.dafscollaborative.org/tools/dafs_api.pdf">the DAFS API's approach to AIO</a>.
<p>
<a href="http://www.ussg.iu.edu/hypermail/linux/kernel/0209.0/0832.html">Red Hat AS</a> and Suse SLES both provide a high-performance implementation on the 2.4 kernel; it is related to, but not completely identical to, the 2.6 kernel implementation. 
</p>
<p>
In February 2006, a new attempt is being made to provide network AIO; see <a href="http://www.kegel.com/c10k.html#kevent">the note above about Evgeniy Polyakov's kevent-based AIO</a>. 
</p>
<p>
In 1999, <strong><a href="http://oss.sgi.com/projects/kaio/">SGI implemented high-speed AIO</a> for Linux</strong>. As of version 1.1, it's said to work well with both disk I/O and sockets. It seems to use kernel threads. It is still useful for people who can't wait for Ben's AIO to support sockets. 
</p>
<p>
The O'Reilly book <a href="http://www.oreilly.com/catalog/posix4/">POSIX.4: Programming for the Real World</a> is said to include a good introduction to aio. 
</p>
<p>
A tutorial for the earlier, nonstandard, aio implementation on Solaris is online at <a href="http://sunsite.nstu.nsk.su/sunworldonline/swol-03-1996/swol-03-aio.html">Sunsite</a>. It's probably worth a look, but keep in mind you'll need to mentally convert &quot;aioread&quot; to &quot;aio_read&quot;, etc. 
</p>
<p>
Note that AIO doesn't provide a way to open files without blocking for disk I/O; if you care about the sleep caused by opening a disk file, <a href="http://www.ussg.iu.edu/hypermail/linux/kernel/0102.1/0124.html">Linus suggests</a> you should simply do the open() in a different thread rather than wishing for an aio_open() system call. 
</p>
<p>
Under Windows, asynchronous I/O is associated with the terms &quot;Overlapped I/O&quot; and IOCP or &quot;I/O Completion Port&quot;. Microsoft's IOCP combines techniques from the prior art like asynchronous I/O (like aio_write) and queued completion notification (like when using the aio_sigevent field with aio_write) with a new idea of holding back some requests to try to keep the number of running threads associated with a single IOCP constant. For more information, see <a href="http://www.sysinternals.com/ntw2k/info/comport.shtml">Inside I/O Completion Ports</a> by Mark Russinovich at sysinternals.com, Jeffrey Richter's book &quot;Programming Server-Side Applications for Microsoft Windows 2000&quot; (<a href="http://www.amazon.com/exec/obidos/ASIN/0735607532">Amazon</a>, <a href="http://www.microsoft.com/mspress/books/toc/3402.asp">MSPress</a>), <a href="http://patft.uspto.gov/netacgi/nph-Parser?Sect1=PTO1&amp;Sect2=HITOFF&amp;d=PALL&amp;p=1&amp;u=/netahtml/srchnum.htm&amp;r=1&amp;f=G&amp;l=50&amp;s1='6223207'.WKU.&amp;OS=PN/6223207&amp;RS=PN/6223207">U.S. patent #06223207</a>, or <a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/fileio/filesio_4z1v.asp">MSDN</a>. 
</p>
<h3><a name="threaded" title="threaded"></a>4. Serve one client with each server thread</h3>
<p>
... and let read() and write() block. Has the disadvantage of using a whole stack frame for each client, which costs memory. Many OS's also have trouble handling more than a few hundred threads. If each thread gets a 2MB stack (not an uncommon default value), you run out of *virtual memory* at (2^30 / 2^21) = 512 threads on a 32 bit machine with 1GB user-accessible VM (like, say, Linux as normally shipped on x86). You can work around this by giving each thread a smaller stack, but since most thread libraries don't allow growing thread stacks once created, doing this means designing your program to minimize stack use. You can also work around this by moving to a 64 bit processor. 
</p>
<p>
The thread support in Linux, FreeBSD, and Solaris is improving, and 64 bit processors are just around the corner even for mainstream users. Perhaps in the not-too-distant future, those who prefer using one thread per client will be able to use that paradigm even for 10000 clients. Nevertheless, at the current time, if you actually want to support that many clients, you're probably better off using some other paradigm. 
</p>
<p>
For an unabashedly pro-thread viewpoint, see <a href="http://www.usenix.org/events/hotos03/tech/vonbehren.html">Why Events Are A Bad Idea (for High-concurrency Servers)</a> by von Behren, Condit, and Brewer, UCB, presented at HotOS IX. Anyone from the anti-thread camp care to point out a paper that rebuts this one? :-) 
</p>
<h4><a name="threads.linuxthreads" title="threads.linuxthreads"></a>LinuxThreads</h4>
<a href="http://pauillac.inria.fr/~xleroy/linuxthreads/">LinuxTheads</a> is the name for the standard Linux thread library. It is integrated into glibc since glibc2.0, and is mostly Posix-compliant, but with less than stellar performance and signal support.
<h4><a name="threads.ngpt" title="threads.ngpt"></a>NGPT: Next Generation Posix Threads for Linux</h4>
<a href="http://www-124.ibm.com/pthreads/">NGPT</a> is a project started by IBM to bring good Posix-compliant thread support to Linux. It's at stable version 2.2 now, and works well... but the NGPT team has <a href="http://www-124.ibm.com/pthreads/docs/announcement">announced</a> that they are putting the NGPT codebase into support-only mode because they feel it's &quot;the best way to support the community for the long term&quot;. The NGPT team will continue working to improve Linux thread support, but now focused on improving NPTL. (Kudos to the NGPT team for their good work and the graceful way they conceded to NPTL.)
<h4><a name="threads.nptl" title="threads.nptl"></a>NPTL: Native Posix Thread Library for Linux</h4>
<a href="http://people.redhat.com/drepper/nptl/">NPTL</a> is a project by <a href="http://people.redhat.com/drepper/">Ulrich Drepper</a> (the benevolent dict^H^H^H^Hmaintainer of <a href="http://www.gnu.org/software/libc/">glibc</a>) and <a href="http://people.redhat.com/mingo/">Ingo Molnar</a> to bring world-class Posix threading support to Linux.
<p>
As of 5 October 2003, NPTL is now merged into the glibc cvs tree as an add-on directory (just like linuxthreads), so it will almost certainly be released along with the next release of glibc. 
</p>
<p>
The first major distribution to include an early snapshot of NPTL was Red Hat 9. (This was a bit inconvenient for some users, but somebody had to break the ice...) 
</p>
<p>
NPTL links: 
</p>
<ul>
	<li><a href="https://listman.redhat.com/mailman/listinfo/phil-list">Mailing list for NPTL discussion</a> </li>
	<li><a href="http://people.redhat.com/drepper/nptl/">NPTL source code</a> </li>
	<li><a href="http://lwn.net/Articles/10465/">Initial announcement for NPTL</a> </li>
	<li><a href="http://people.redhat.com/drepper/glibcthreads.html">Original whitepaper describing the goals for NPTL</a> </li>
	<li><a href="http://people.redhat.com/drepper/nptl-design.pdf">Revised whitepaper describing the final design of NPTL</a> </li>
	<li><a href="http://marc.theaimsgroup.com/?l=linux-kernel&amp;m=103230439008204&amp;w=2">Ingo Molnar's</a> first benchmark showing it could handle 10^6 threads </li>
	<li><a href="http://marc.theaimsgroup.com/?l=linux-kernel&amp;m=103269598000900&amp;w=2">Ulrich's benchmark</a> comparing performance of LinuxThreads, NPTL, and IBM's <a href="http://www.kegel.com/c10k.html#threads.ngpt">NGPT</a>. It seems to show NPTL is much faster than NGPT. </li>
</ul>
Here's my try at describing the history of NPTL (see also <a href="http://www.onlamp.com/pub/a/onlamp/2002/11/07/linux_threads.html">Jerry Cooperstein's article</a>):
<p>
<a href="http://people.redhat.com/drepper/glibcthreads.html">In March 2002, Bill Abt of the NGPT team, the glibc maintainer Ulrich Drepper, and others met</a> to figure out what to do about LinuxThreads. One idea that came out of the meeting was to improve mutex performance; Rusty Russell <a href="http://marc.theaimsgroup.com/?l=linux-kernel&amp;m=103284847815916&amp;w=2">et al</a> subsequently implemented <a href="http://marc.theaimsgroup.com/?l=linux-kernel&amp;m=102196625921110&amp;w=2">fast userspace mutexes (futexes)</a>), which are now used by both NGPT and NPTL. Most of the attendees figured NGPT should be merged into glibc. 
</p>
<p>
Ulrich Drepper, though, didn't like NGPT, and figured he could do better. (For those who have ever tried to contribute a patch to glibc, this may not come as a big surprise :-) Over the next few months, Ulrich Drepper, Ingo Molnar, and others contributed glibc and kernel changes that make up something called the Native Posix Threads Library (NPTL). NPTL uses all the kernel enhancements designed for NGPT, and takes advantage of a few new ones. Ingo Molnar <a href="https://listman.redhat.com/pipermail/phil-list/2002-September/000013.html">described</a> the kernel enhancements as follows: 
</p>
<blockquote>
	<em>While NPTL uses the three kernel features introduced by NGPT: getpid() returns PID, CLONE_THREAD and futexes; NPTL also uses (and relies on) a much wider set of new kernel features, developed as part of this project.
	<p>
	Some of the items NGPT introduced into the kernel around 2.5.8 got modified, cleaned up and extended, such as thread group handling (CLONE_THREAD). [the CLONE_THREAD changes which impacted NGPT's compatibility got synced with the NGPT folks, to make sure NGPT does not break in any unacceptable way.] 
	</p>
	<p>
	The kernel features developed for and used by NPTL are described in the design whitepaper, http://people.redhat.com/drepper/nptl-design.pdf ... 
	</p>
	<p>
	A short list: TLS support, various clone extensions (CLONE_SETTLS, CLONE_SETTID, CLONE_CLEARTID), POSIX thread-signal handling, sys_exit() extension (release TID futex upon VM-release), the sys_exit_group() system-call, sys_execve() enhancements and support for detached threads. 
	</p>
	<p>
	There was also work put into extending the PID space - eg. procfs crashed due to 64K PID assumptions, max_pid, and pid allocation scalability work. Plus a number of performance-only improvements were done as well. 
	</p>
	<p>
	In essence the new features are a no-compromises approach to 1:1 threading - the kernel now helps in everything where it can improve threading, and we precisely do the minimally necessary set of context switches and kernel calls for every basic threading primitive. 
	</p>
	</em>
</blockquote>
One big difference between the two is that NPTL is a 1:1 threading model, whereas NGPT is an M:N threading model (see below). In spite of this, <a href="https://listman.redhat.com/pipermail/phil-list/2002-September/000009.html">Ulrich's initial benchmarks</a> seem to show that NPTL is indeed much faster than NGPT. (The NGPT team is looking forward to seeing Ulrich's benchmark code to verify the result.)
<h4><a name="threads.freebsd" title="threads.freebsd"></a>FreeBSD threading support</h4>
FreeBSD supports both LinuxThreads and a userspace threading library. Also, a M:N implementation called KSE was introduced in FreeBSD 5.0. For one overview, see <a href="http://www.unobvious.com/bsd/freebsd-threads.html">www.unobvious.com/bsd/freebsd-threads.html</a>.
<p>
On 25 Mar 2003, <a href="http://docs.freebsd.org/cgi/getmsg.cgi?fetch=121207+0+archive/2003/freebsd-arch/20030330.freebsd-arch">Jeff Roberson posted on freebsd-arch</a>: 
</p>
<blockquote>
	<em>... Thanks to the foundation provided by Julian, David Xu, Mini, Dan Eischen, and everyone else who has participated with KSE and libpthread development Mini and I have developed a 1:1 threading implementation. This code works in parallel with KSE and does not break it in any way. It actually helps bring M:N threading closer by testing out shared bits. ... </em>
</blockquote>
And in July 2006, <a href="http://marc.theaimsgroup.com/?l=freebsd-threads&amp;m=115191979412894&amp;w=2">Robert Watson proposed that the 1:1 threading implementation become the default in FreeBsd 7.x</a>: 
<blockquote>
	<em>I know this has been discussed in the past, but I figured with 7.x trundling forward, it was time to think about it again. In benchmarks for many common applications and scenarios, libthr demonstrates significantly better performance over libpthread... libthr is also implemented across a larger number of our platforms, and is already libpthread on several. The first recommendation we make to MySQL and other heavy thread users is &quot;Switch to libthr&quot;, which is suggestive, also! ... So the strawman proposal is: make libthr the default threading library on 7.x. </em>
</blockquote>
<h4><a name="threads.netbsd" title="threads.netbsd"></a>NetBSD threading support</h4>
According to a note from Noriyuki Soda: 
<blockquote>
	<em>Kernel supported M:N thread library based on the Scheduler Activations model is merged into NetBSD-current on Jan 18 2003. </em>
</blockquote>
For details, see <a href="http://web.mit.edu/nathanw/www/usenix/freenix-sa/">An Implementation of Scheduler Activations on the NetBSD Operating System</a> by Nathan J. Williams, Wasabi Systems, Inc., presented at FREENIX '02.
<h4><a name="threads.solaris" title="threads.solaris"></a>Solaris threading support</h4>
The thread support in Solaris is evolving... from Solaris 2 to Solaris 8, the default threading library used an M:N model, but Solaris 9 defaults to 1:1 model thread support. See <a href="http://docs.sun.com/db/doc/805-5080">Sun's multithreaded programming guide</a> and <a href="http://java.sun.com/docs/hotspot/threads/threads.html">Sun's note about Java and Solaris threading</a>.
<h4><a name="threads.java" title="threads.java"></a>Java threading support in JDK 1.3.x and earlier</h4>
As is well known, Java up to JDK1.3.x did not support any method of handling network connections other than one thread per client. <a href="http://www.volano.com/report/">Volanomark</a> is a good microbenchmark which measures throughput in messsages per second at various numbers of simultaneous connections. As of May 2003, JDK 1.3 implementations from various vendors are in fact able to handle ten thousand simultaneous connections -- albeit with significant performance degradation. See <a href="http://www.volano.com/report/#nettable">Table 4</a> for an idea of which JVMs can handle 10000 connections, and how performance suffers as the number of connections increases.
<h4><a name="1:1" title="1:1"></a>Note: 1:1 threading vs. M:N threading</h4>
There is a choice when implementing a threading library: you can either put all the threading support in the kernel (this is called the 1:1 threading model), or you can move a fair bit of it into userspace (this is called the M:N threading model). At one point, M:N was thought to be higher performance, but it's so complex that it's hard to get right, and most people are moving away from it.
<ul>
	<li><a href="http://marc.theaimsgroup.com/?l=linux-kernel&amp;m=103284879216107&amp;w=2">Why Ingo Molnar prefers 1:1 over M:N</a> </li>
	<li><a href="http://java.sun.com/docs/hotspot/threads/threads.html">Sun is moving to 1:1 threads</a> </li>
	<li><a href="http://www-124.ibm.com/pthreads/">NGPT</a> is an M:N threading library for Linux. </li>
	<li>Although <a href="http://people.redhat.com/drepper/glibcthreads.html">Ulrich Drepper planned to use M:N threads in the new glibc threading library</a>, he has since <a href="http://people.redhat.com/drepper/nptl-design.pdf">switched to the 1:1 threading model.</a> </li>
	<li><a href="http://developer.apple.com/technotes/tn/tn2028.html#MacOSXThreading">MacOSX appears to use 1:1 threading.</a> </li>
	<li><a href="http://people.freebsd.org/~julian/">FreeBSD</a> and <a href="http://web.mit.edu/nathanw/www/usenix/freenix-sa/">NetBSD</a> appear to still believe in M:N threading... The lone holdouts? Looks like freebsd 7.0 might switch to 1:1 threading (see above), so perhaps M:N threading's believers have finally been proven wrong everywhere. </li>
</ul>
<h3><a name="kio" title="kio"></a>5. Build the server code into the kernel</h3>
<p>
Novell and Microsoft are both said to have done this at various times, at least one NFS implementation does this, <a href="http://www.fenrus.demon.nl/">khttpd</a> does this for Linux and static web pages, and <a href="http://slashdot.org/comments.pl?sid=00/07/05/0211257&amp;cid=218">&quot;TUX&quot; (Threaded linUX webserver)</a> is a blindingly fast and flexible kernel-space HTTP server by Ingo Molnar for Linux. Ingo's <a href="http://marc.theaimsgroup.com/?l=linux-kernel&amp;m=98098648011183&amp;w=2">September 1, 2000 announcement</a> says an alpha version of TUX can be downloaded from <a href="ftp://ftp.redhat.com/pub/redhat/tux">ftp://ftp.redhat.com/pub/redhat/tux</a>, and explains how to join a mailing list for more info. <br />
The linux-kernel list has been discussing the pros and cons of this approach, and the consensus seems to be instead of moving web servers into the kernel, the kernel should have the smallest possible hooks added to improve web server performance. That way, other kinds of servers can benefit. See e.g. <a href="http://www.linuxhq.com/lnxlists/linux-kernel/lk_9906_03/msg01041.html">Zach Brown's remarks</a> about userland vs. kernel http servers. It appears that the 2.4 linux kernel provides sufficient power to user programs, as the <a href="http://www.kegel.com/c10k.html#x15">X15</a> server runs about as fast as Tux, but doesn't use any kernel modifications. 
</p>
<p>
&nbsp;
</p>
<h2><a name="comments" title="comments"></a>Comments</h2>
<p>
Richard Gooch has written <a href="http://www.atnf.csiro.au/~rgooch/linux/docs/io-events.html">a paper discussing I/O options</a>. 
</p>
<p>
In 2001, Tim Brecht and MMichal Ostrowski <a href="http://www.hpl.hp.com/techreports/2001/HPL-2001-314.html">measured various strategies</a> for simple select-based servers. Their data is worth a look. 
</p>
<p>
In 2003, Tim Brecht posted <a href="http://www.hpl.hp.com/research/linux/userver/">source code for userver</a>, a small web server put together from several servers written by Abhishek Chandra, David Mosberger, David Pariag, and Michal Ostrowski. It can use select(), poll(), epoll(), or sigio. 
</p>
<p>
Back in March 1999, <a href="http://marc.theaimsgroup.com/?l=apache-httpd-dev&amp;m=92100977123493&amp;w=2">Dean Gaudet posted</a>: 
</p>
<blockquote>
	<em>I keep getting asked &quot;why don't you guys use a select/event based model like Zeus? It's clearly the fastest.&quot; ... </em>
</blockquote>
His reasons boiled down to &quot;it's really hard, and the payoff isn't clear&quot;. Within a few months, though, it became clear that people were willing to work on it.
<p>
Mark Russinovich wrote <a href="http://linuxtoday.com/stories/5499.html">an editorial</a> and <a href="http://www.winntmag.com/Articles/Index.cfm?ArticleID=5048">an article</a> discussing I/O strategy issues in the 2.2 Linux kernel. Worth reading, even he seems misinformed on some points. In particular, he seems to think that Linux 2.2's asynchronous I/O (see F_SETSIG above) doesn't notify the user process when data is ready, only when new connections arrive. This seems like a bizarre misunderstanding. See also <a href="http://www.dejanews.com/getdoc.xp?AN=431444525">comments on an earlier draft</a>, <a href="http://www.dejanews.com/getdoc.xp?AN=472893693">Ingo Molnar's rebuttal of 30 April 1999</a>, <a href="http://www.linuxhq.com/lnxlists/linux-kernel/lk_9905_01/msg00089.html">Russinovich's comments of 2 May 1999</a>, <a href="http://www.linuxhq.com/lnxlists/linux-kernel/lk_9905_01/msg00263.html">a rebuttal</a> from Alan Cox, and various <a href="http://www.dejanews.com/dnquery.xp?ST=PS&amp;QRY=threads&amp;DBS=1&amp;format=threaded&amp;showsort=score&amp;maxhits=100&amp;LNG=ALL&amp;groups=fa.linux.kernel+&amp;fromdate=jun+1+1998">posts to linux-kernel</a>. I suspect he was trying to say that Linux doesn't support asynchronous disk I/O, which used to be true, but now that SGI has implemented <a href="http://www.kegel.com/c10k.html#aio">KAIO</a>, it's not so true anymore. 
</p>
<p>
See these pages at <a href="http://www.sysinternals.com/ntw2k/info/comport.shtml">sysinternals.com</a> and <a href="http://msdn.microsoft.com/library/techart/msdn_scalabil.htm">MSDN</a> for information on &quot;completion ports&quot;, which he said were unique to NT; in a nutshell, win32's &quot;overlapped I/O&quot; turned out to be too low level to be convenient, and a &quot;completion port&quot; is a wrapper that provides a queue of completion events, plus scheduling magic that tries to keep the number of running threads constant by allowing more threads to pick up completion events if other threads that had picked up completion events from this port are sleeping (perhaps doing blocking I/O). 
</p>
<p>
See also <a href="http://www.as400.ibm.com/developer/v4r5/api.html">OS/400's support for I/O completion ports</a>. 
</p>
<p>
<a name="15k" title="15k"></a>There was an interesting discussion on linux-kernel in September 1999 titled &quot;<a href="http://www.cs.helsinki.fi/linux/linux-kernel/Year-1999/1999-36/0160.html">&gt; 15,000 Simultaneous Connections</a>&quot; (and the <a href="http://www.cs.helsinki.fi/linux/linux-kernel/Year-1999/1999-37/0612.html">second week</a> of the thread). Highlights: 
</p>
<ul>
	<li>Ed Hall <a href="http://www.linuxhq.com/lnxlists/linux-kernel/lk_9909_01/msg00807.html">posted</a> a few notes on his experiences; he's achieved &gt;1000 connects/second on a UP P2/333 running Solaris. His code used a small pool of threads (1 or 2 per CPU) each managing a large number of clients using &quot;an event-based model&quot;. </li>
	<li>Mike Jagdis <a href="http://www.linuxhq.com/lnxlists/linux-kernel/lk_9909_01/msg00831.html">posted an analysis of poll/select overhead</a>, and said &quot;The current select/poll implementation can be improved significantly, especially in the blocking case, but the overhead will still increase with the number of descriptors because select/poll does not, and cannot, remember what descriptors are interesting. This would be easy to fix with a new API. Suggestions are welcome...&quot; </li>
	<li>Mike <a href="http://www.linuxhq.com/lnxlists/linux-kernel/lk_9909_01/msg00964.html">posted</a> about his <a href="http://www.purplet.demon.co.uk/linux/select/">work on improving select() and poll()</a>. </li>
	<li>Mike <a href="http://www.linuxhq.com/lnxlists/linux-kernel/lk_9909_01/msg00971.html">posted a bit about a possible API to replace poll()/select()</a>: &quot;How about a 'device like' API where you write 'pollfd like' structs, the 'device' listens for events and delivers 'pollfd like' structs representing them when you read it? ... &quot; </li>
	<li>Rogier Wolff <a href="http://www.linuxhq.com/lnxlists/linux-kernel/lk_9909_01/msg00979.html">suggested</a> using &quot;the API that the digital guys suggested&quot;, <a href="http://www.cs.rice.edu/~gaurav/papers/usenix99.ps">http://www.cs.rice.edu/~gaurav/papers/usenix99.ps</a> </li>
	<li>Joerg Pommnitz <a href="http://www.linuxhq.com/lnxlists/linux-kernel/lk_9909_02/msg00001.html">pointed out</a> that any new API along these lines should be able to wait for not just file descriptor events, but also signals and maybe SYSV-IPC. Our synchronization primitives should certainly be able to do what Win32's WaitForMultipleObjects can, at least. </li>
	<li>Stephen Tweedie <a href="http://www.linuxhq.com/lnxlists/linux-kernel/lk_9909_02/msg01198.html">asserted</a> that the combination of F_SETSIG, queued realtime signals, and sigwaitinfo() was a superset of the API proposed in http://www.cs.rice.edu/~gaurav/papers/usenix99.ps. He also mentions that you keep the signal blocked at all times if you're interested in performance; instead of the signal being delivered asynchronously, the process grabs the next one from the queue with sigwaitinfo(). </li>
	<li>Jayson Nordwick <a href="http://www.linuxhq.com/lnxlists/linux-kernel/lk_9909_03/msg00002.html">compared</a> completion ports with the F_SETSIG synchronous event model, and concluded they're pretty similar. </li>
	<li>Alan Cox <a href="http://www.linuxhq.com/lnxlists/linux-kernel/lk_9909_03/msg00043.html">noted</a> that an older rev of SCT's SIGIO patch is included in 2.3.18ac. </li>
	<li>Jordan Mendelson <a href="http://www.linuxhq.com/lnxlists/linux-kernel/lk_9909_03/msg00093.html">posted</a> some example code showing how to use F_SETSIG. </li>
	<li>Stephen C. Tweedie <a href="http://www.linuxhq.com/lnxlists/linux-kernel/lk_9909_03/msg00095.html">continued</a> the comparison of completion ports and F_SETSIG, and noted: &quot;With a signal dequeuing mechanism, your application is going to get signals destined for various library components if libraries are using the same mechanism,&quot; but the library can set up its own signal handler, so this shouldn't affect the program (much). </li>
	<li><a href="http://www.linuxhq.com/lnxlists/linux-kernel/lk_9909_04/msg00900.html">Doug Royer</a> noted that he'd gotten 100,000 connections on Solaris 2.6 while he was working on the Sun calendar server. Others chimed in with estimates of how much RAM that would require on Linux, and what bottlenecks would be hit. </li>
</ul>
<p>
Interesting reading! 
</p>
<p>
&nbsp;
</p>
<h2><a name="limits.filehandles" title="limits.filehandles"></a>Limits on open filehandles</h2>
<ul>
	<li>Any Unix: the limits set by ulimit or setrlimit. </li>
	<li>Solaris: see <a href="http://www.wins.uva.nl/pub/solaris/solaris2/Q3.46.html">the Solaris FAQ, question 3.46</a> (or thereabouts; they renumber the questions periodically). </li>
	<li>FreeBSD:<br />
	<br />
	Edit /boot/loader.conf, add the line
	<pre>
	set kern.maxfiles=XXXX
	</pre>
	where XXXX is the desired system limit on file descriptors, and reboot. Thanks to an anonymous reader, who wrote in to say he'd achieved far more than 10000 connections on FreeBSD 4.3, and says 
	<blockquote>
		&quot;FWIW: You can't actually tune the maximum number of connections in FreeBSD trivially, via sysctl.... You have to do it in the /boot/loader.conf file. <br />
		The reason for this is that the zalloci() calls for initializing the sockets and tcpcb structures zones occurs very early in system startup, in order that the zone be both type stable and that it be swappable. <br />
		You will also need to set the number of mbufs much higher, since you will (on an unmodified kernel) chew up one mbuf per connection for tcptempl structures, which are used to implement keepalive.&quot; 
	</blockquote>
	Another reader says 
	<blockquote>
		&quot;As of FreeBSD 4.4, the tcptempl structure is no longer allocated; you no longer have to worry about one mbuf being chewed up per connection.&quot; 
	</blockquote>
	See also:
	<ul>
		<li><a href="http://www.freebsd.org/doc/en_US.ISO8859-1/books/handbook/configtuning-kernel-limits.html">the FreeBSD handbook</a> </li>
		<li><a href="http://www.freebsd.org/cgi/man.cgi?query=tuning#SYSCTL+TUNING">SYSCTL TUNING</a>, <a href="http://www.freebsd.org/cgi/man.cgi?query=tuning#LOADER+TUNABLES">LOADER TUNABLES</a>, and <a href="http://www.freebsd.org/cgi/man.cgi?query=tuning#KERNEL+CONFIG+TUNING">KERNEL CONFIG TUNING</a> in 'man tuning' </li>
		<li><a href="http://www.daemonnews.org/200108/benchmark.html">The Effects of Tuning a FreeBSD 4.3 Box for High Performance</a>, Daemon News, Aug 2001 </li>
		<li><a href="http://www.postfix.org/faq.html#moby-freebsd">postfix.org tuning notes</a>, covering FreeBSD 4.2 and 4.4 </li>
		<li><a href="http://www.measurement-factory.com/docs/FreeBSD/">the Measurement Factory's notes</a>, circa FreeBSD 4.3 </li>
	</ul>
	</li>
	<li>OpenBSD: A reader says 
	<blockquote>
		&quot;In OpenBSD, an additional tweak is required to increase the number of open filehandles available per process: the openfiles-cur parameter in <a href="http://www.freebsd.org/cgi/man.cgi?query=login.conf&amp;manpath=OpenBSD+3.1">/etc/login.conf</a> needs to be increased. You can change kern.maxfiles either with sysctl -w or in sysctl.conf but it has no effect. This matters because as shipped, the login.conf limits are a quite low 64 for nonprivileged processes, 128 for privileged.&quot; 
	</blockquote>
	</li>
	<li>Linux: See <a href="http://asc.di.fct.unl.pt/~jml/mirror/Proc/">Bodo Bauer's /proc documentation</a>. On 2.4 kernels:
	<pre>
	echo 32768 &gt; /proc/sys/fs/file-max
	</pre>
	increases the system limit on open files, and
	<pre>
	ulimit -n 32768
	</pre>
	increases the current process' limit.
	<p>
	On 2.2.x kernels, 
	</p>
	<pre>
	echo 32768 &gt; /proc/sys/fs/file-max
	echo 65536 &gt; /proc/sys/fs/inode-max
	</pre>
	increases the system limit on open files, and
	<pre>
	ulimit -n 32768
	</pre>
	increases the current process' limit.
	<p>
	I verified that a process on Red Hat 6.0 (2.2.5 or so plus patches) can open at least 31000 file descriptors this way. Another fellow has verified that a process on 2.2.12 can open at least 90000 file descriptors this way (with appropriate limits). The upper bound seems to be available memory. <br />
	Stephen C. Tweedie <a href="http://www.linuxhq.com/lnxlists/linux-kernel/lk_9909_02/msg01092.html">posted</a> about how to set ulimit limits globally or per-user at boot time using initscript and pam_limit. <br />
	In older 2.2 kernels, though, the number of open files per process is still limited to 1024, even with the above changes. <br />
	See also <a href="http://www.dejanews.com/getdoc.xp?AN=313316592">Oskar's 1998 post</a>, which talks about the per-process and system-wide limits on file descriptors in the 2.0.36 kernel. 
	</p>
	</li>
</ul>
<h2><a name="limits.threads" title="limits.threads"></a>Limits on threads</h2>
<p>
On any architecture, you may need to reduce the amount of stack space allocated for each thread to avoid running out of virtual memory. You can set this at runtime with pthread_attr_init() if you're using pthreads. 
</p>
<ul>
	<li>Solaris: it supports as many threads as will fit in memory, I hear. </li>
	<li>Linux 2.6 kernels with NPTL: /proc/sys/vm/max_map_count may need to be increased to go above 32000 or so threads. (You'll need to use very small stack threads to get anywhere near that number of threads, though, unless you're on a 64 bit processor.) See the NPTL mailing list, e.g. the thread with subject &quot;<a href="https://listman.redhat.com/archives/phil-list/2003-August/msg00005.html">Cannot create more than 32K threads?</a>&quot;, for more info. </li>
	<li>Linux 2.4: /proc/sys/kernel/threads-max is the max number of threads; it defaults to 2047 on my Red Hat 8 system. You can set increase this as usual by echoing new values into that file, e.g. &quot;echo 4000 &gt; /proc/sys/kernel/threads-max&quot; </li>
	<li>Linux 2.2: Even the 2.2.13 kernel limits the number of threads, at least on Intel. I don't know what the limits are on other architec</li></ul>
          <br/>
          <span style="color:red;">
            <a href="http://dustin.javaeye.com/blog/134563#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Mon, 22 Oct 2007 19:44:05 +0800</pubDate>
        <link>http://dustin.javaeye.com/blog/134563</link>
        <guid>http://dustin.javaeye.com/blog/134563</guid>
      </item>
      <item>
        <title>宜宾记忆</title>
        <author>Dustin</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://dustin.javaeye.com">Dustin</a>&nbsp;
          链接：<a href="http://dustin.javaeye.com/blog/126206" style="color:red;">http://dustin.javaeye.com/blog/126206</a>&nbsp;
          发表时间: 2007年09月22日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <div goog_ds_charindex="70"><font size="3" goog_ds_charindex="71"><span goog_ds_charindex="72"><font goog_ds_charindex="73">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;偷得浮生半日闲已是相当惬意，殊不知晃眼已是半月。从记事起，夏天一直是个忙碌的季节，总要忙学习，忙项目的，今年却是例外。&nbsp;</font></span></font></div>
<div goog_ds_charindex="70"><font size="3" goog_ds_charindex="71"><span goog_ds_charindex="72">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span goog_ds_charindex="82">假期就要结束，此时正在宜宾，我就在这美丽的地方过了一个&ldquo;奢侈&rdquo;的假期。宜宾地理位置可谓得天独厚，岷江、金沙江在此聚入长江，滚滚东去，站在地标广场，顺着&ldquo;泾渭分明&rdquo;的江水，似乎可以看到遥远的东海岸。</span></font> </div>
<div goog_ds_charindex="185" style="TEXT-INDENT: 10.5pt"><font size="3" goog_ds_charindex="186"><span goog_ds_charindex="187">&nbsp;&nbsp; 翠屏山葱葱郁郁，矗立在城市的中心地带。虽然不高，只有</span><span goog_ds_charindex="216"><font goog_ds_charindex="217">502</font></span><span goog_ds_charindex="223">米，但是对我而言仍然是个不小的挑战。一直以为，我跟崇山峻岭的缘分自西岭一役从此灰飞烟灭，想不到还是忍不住继续挑战自己的极限，幸好成功登顶了，爬上三江一览塔，一览三江汇聚的神奇景象，体会了一下气吞万里的&ldquo;万里长江第一城&rdquo;的豪迈。途中还看到了千佛寺和哪吒洞，没想到哪吒洞还要收取人民币</span><span goog_ds_charindex="365"><font goog_ds_charindex="366">2</font></span><span goog_ds_charindex="370">元整，心想我们大老远跑过来看望你老人家，爬山还累了个半死，竟然还要收费，一气之下挥袖而去，硬是没有进去，不服都不行。此行得出两个结论，一是登山确非我强项，以后切不可争强好胜，妄想征名山大川，当然有索道的除外；二是虽然</span><span goog_ds_charindex="480"><font goog_ds_charindex="481">Loya</font></span><span goog_ds_charindex="488">看似缺乏运动细胞，但登山硬是一把好手，穿着双拖板鞋，流了一头汗就把翠屏山蹂躏了，敬仰，敬仰。</span></font> </div>
<div goog_ds_charindex="539" style="TEXT-INDENT: 10.5pt"><font size="3" goog_ds_charindex="540"><span goog_ds_charindex="541">说到宜宾不能不提五粮液，这里的三江之水孕育了神州琼浆，五粮液也向世人展示了这片神奇的土地。晚饭后散步至此天已渐黑，朦胧中看着笔直开阔的五粮液大道，望着那矗立的大门，还有路旁一个个神态各异的雕像以及国家领导人的&ldquo;谆谆教导&rdquo;，你能感受到这瓶酒在宜宾人心中的地位。路边的李白潇洒依旧，才知道当年的诗仙是喝着五粮液来吟诗作对的，怪不得&ldquo;一斗酒，诗百篇&rdquo;。想想老人家若是活在当前，喝着动辄上千的琼浆，兜里是否有充足的酒钱让他留下华章千篇呢。</span></font><font size="3" goog_ds_charindex="759"><span goog_ds_charindex="760">酒城内熙来攘往，bus，taxi俱全，一鼓作气跑上了酒圣山，爬上了大蘑菇（动作依然敏捷，立马引来粉丝一个，骄傲！），可见之处均是酒城，好一个城中之城。空气之中弥漫着淡淡的醇香，不禁深深呼吸了几下，嘿嘿，算是品尝过了吧。（听说可以免费喝的，但是&ldquo;导游&rdquo;没带我去）</span></font> </div>
<div goog_ds_charindex="895" style="TEXT-INDENT: 10.5pt"><font size="3" goog_ds_charindex="896"><span goog_ds_charindex="897"><font goog_ds_charindex="898">以前Loya</font></span><span goog_ds_charindex="907">一说要吃臭豆腐，我总拿工商管理人员的恐怖经历来教育她，希望她意识到臭豆腐这东西不但闻起来臭，吃起来臭，而且想起来也是臭的，没想到宜宾的臭豆腐却成了我最喜欢的小吃。老大娘一番捣鼓，马上化腐朽为神奇，刚刚还奇臭无比的豆腐转眼变得有滋有味的，让我想起了已远去多年的梅香咸鱼。</span></font> <span goog_ds_charindex="1045"><font size="3" goog_ds_charindex="1046">这里的面条油而不腻，面身劲道，特别爽口，而且还品种繁多，排骨面，肥肠面，生椒牛肉面，荤燃面，之如此类，难以胜数，我喜欢。Loya每天早上都要跑去吃上一碗，而且每次把面汤都喝得一干二净的，说宜宾面条的精髓在于汤。这对我也有莫大的吸引力，奈何出来之前已被&ldquo;勒令&rdquo;喝了一大碗牛奶外加一个大鸡蛋，叫我如何消受呢。点点香也是个好东西，隐藏在林家巷一个不显眼的角落里，铺面有点陈旧，但是客人暴多，好不容易才在二楼找到个坐的地方。各色菜蔬放在一起，加上辣椒孜然，有点像平时的冒菜，但是更香，更为开胃爽口。但是令人不解的是，这么一个怡人的美味，吃了却要拉肚子。。吃过两次，每次都要吃几颗肠炎宁才从水深火热中挣扎出来，郁闷。期间还吃了些以前闻所未闻或者闻过却没吃过的小玩意，什么凉粉，凉虾，冰粉，炎炎夏日，边走边吃确实别有一番风味，特别那个黑凉粉里面还加了薄荷，口感奇特，令人难忘。</font></span> </div>
<div goog_ds_charindex="1433" style="TEXT-INDENT: 10.5pt"><span goog_ds_charindex="1434"><font size="3" goog_ds_charindex="1435">Loya确实不是一个好导游，一些名胜典故全然不知，宜宾到处都是&ldquo;叙府&rdquo;，她竟然不知出处。有来由吗？没来由吗？不知道！我的好奇心就这样被摧残了，默哀一下。然而，她确实是一个地道的老宜宾，这体现在她对宜宾各大商场小摊地理位置的准确掌握上。据Loya老妈回忆，她女儿一个最大的嗜好就是遍历宜宾各大超市，因而练就一双可以&ldquo;踏破铁鞋&rdquo;的&ldquo;无敌飞腿&rdquo;。终于知道翠屏山在她面前为什么如此不堪一击了。逛街散步是这段时间的主要活动，足迹遍布宜宾城区的各个角落。回想一下，大观楼至Loya家这条线路走了不下10次了吧，连我这个路痴看到大观楼后脑海中都可以展现出一条清晰的回家路线了。饭后散步确是一件惬意的事情，享受着江面送来的凉风，沐浴在路旁昏黄的灯光下，分享着一天的喜怒哀乐，不时还能看到一大群人在音乐声中翩翩起舞，其中男女老少，不分你我，乐在其中。在这烦躁的社会，每天能有这么一个恬静的角落，让疲惫的心灵得以喘息，实为一大幸事。不知道若干年后的我，是否还能持有这样一份心情呢？</font></span></div>
<div goog_ds_charindex="1433" style="TEXT-INDENT: 10.5pt"><span goog_ds_charindex="1434"><font size="3">一星期眨眼就过去了，我们慢慢意识到&ldquo;饭来张口，衣来伸手&rdquo;确实不是21世纪有为青年该有的作风，因此决定每天要亲自下厨，一展厨艺。奈何平时并无多少积累，连以前引以为豪的&ldquo;肉末蒸蛋&rdquo;都被人鄙视了，因此也打消了让它重新上场的念头，免得贻笑大方。幸好当今世界有互联网和搜索引擎这样美妙的东西。&ldquo;百度一下，你就知道&rdquo;，果不其然！在网上找到各色美食的菜谱后，在专家带领下到菜市场把材料购置妥当，然后就如&ldquo;</font></span><span goog_ds_charindex="1434"><font size="3">看图说话&rdquo;般，一步一步捣弄起来。在家的时候我还是做过饭滴，基本功摆在那里，虽然有点笨手笨脚，但成品看起来还是像模像样的：鱼香茄子，清蒸排骨，排骨玉米汤，皮蛋瘦肉粥，陈皮老鸭，可以说是硕果累累阿。当然也有不足啦：第一次鱼香茄子油放得太多了，难以下咽；清蒸排骨时把酱油当成生抽来用，结果咸得难以入口；鸭子本来是用来做酸梅鸭的，谁晓得逛遍宜宾所有超市都找不到酸梅酱，Loya灵机一动，说买包九制话梅回去试一下，结果现在的话梅都是甜的，哪来酸味呢，只好作罢转做陈皮老鸭。呵呵，这陈皮还是从成都带过去的，&ldquo;佳宝&rdquo;牌，奉劝大家，这东东用来当零食还可以，但是用来做菜确实不是一般的难吃：）Loya当然不甘人后，而且身手不凡：贵妃鸡翅，南瓜栗子饼，西红柿焖牛肉都是她的得意之作。现在想想，多少有点思念之情了，口水ing~</font></span></div>
<div goog_ds_charindex="1433" style="TEXT-INDENT: 10.5pt"><span goog_ds_charindex="1434"><font size="3">吃饭本来是一件赏心悦目之事，特别是我们这些平时在饭堂吃饭缺少荤腥之人，加上菜肴如此丰盛美味，当然喜不自禁。但一段时间后，在大鱼大肉的狂轰滥炸之下，我的肠胃逐渐丧失了原有的战斗力。叔叔阿姨看到我干瞪眼不动筷，以为我突然客气起来了，于是对我热情洋溢来一句：&ldquo;小张，吃！&rdquo;却之不恭，我马上把肉往嘴里塞，说：&ldquo;好！&rdquo;就这样，慢慢地，我发现自己竟然长胖了，真是个奇迹。</font></span></div>
<div goog_ds_charindex="1433" style="TEXT-INDENT: 10.5pt"><span goog_ds_charindex="1434"><font size="3">马上又是九月了，假期到此结束，又要开始忙碌。住的地方名叫西郊加气站，希望它也能给我们加加气，把疲惫甩开，精力充沛地迎接后面的日子吧。</font></span></div>
<div goog_ds_charindex="1433" style="TEXT-INDENT: 10.5pt"><span goog_ds_charindex="1434"><font size="3">宜宾，走了。</font></span></div>
          <br/>
          <span style="color:red;">
            <a href="http://dustin.javaeye.com/blog/126206#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Sat, 22 Sep 2007 22:03:37 +0800</pubDate>
        <link>http://dustin.javaeye.com/blog/126206</link>
        <guid>http://dustin.javaeye.com/blog/126206</guid>
      </item>
      <item>
        <title>SaaS 软件即服务</title>
        <author>Dustin</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://dustin.javaeye.com">Dustin</a>&nbsp;
          链接：<a href="http://dustin.javaeye.com/blog/98828" style="color:red;">http://dustin.javaeye.com/blog/98828</a>&nbsp;
          发表时间: 2007年07月07日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <p>
&nbsp; SaaS( Software as a Service)模式现在是越来越普遍了。对于软件供应商来说，软件可以集中管理，升级维护方便，省心省力，而且以互联网为分发渠道，采取 muti-tenant能很好地发掘潜在客户（各个中小客户），发挥长尾效应的威力，赢取最大的经济效益；对于客户而言，省去了维护专有系统的的人力和经济花销，而且SaaS采用的 pay as you go模式能极大减少中小客户的资金压力，相当有说服力。<br />
&nbsp;&nbsp; 说起SaaS，大家都会不约而同地提到ASP(Application Service Provider,这里不是MS的Active Server Page:) )。对我而言，ASP完全是一个陌生人，查了一下资料才知道这哥们是上世纪90年代的红人，可惜现在风光不再，相关新闻都是跟到SaaS后面当反面例子，而且用得最多的形容词也是惨不忍睹的totally completely failed。。ASP看上去跟SaaS很像，两者都是通过Browser 进行操作，通过网络隔离用用户和软件供应商；同样是把应用软件交给第三方进行托管等。自然，人们也就担心SaaS是否会重覆ASP的倒辙，落下个一地鸡毛的下场。<br />
&nbsp; 但是，SaaS在这几年迅速上位，自然有其过人之处。可以先看看SaaS跟ASP之间的区别【form wiki】：<br />
&nbsp;&nbsp;&nbsp;&nbsp; <span style="font-family: Arial">1. ASP applications are traditional single-tenant applications but hosted by a third party. They are client-server applications with HTML front ends added to allow remote access to the application.<br />
&nbsp;&nbsp;&nbsp; 2. The applications are hosted by third-parties who ordinarily do not have specific application expertise.<br />
&nbsp;&nbsp;&nbsp; 3. The applications are not written as net-native applications. As a result, the performance may be poor and application updates are no better than self-managed premise-base applications.<br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp; </span>此外，随着网络带宽的增加，网络技术的发展（如Ajax），用户的使用体验必定大为增强，这也是SaaS可以繁盛起来的重要原因。
</p>
<p>
<br />
有兴趣的可以看看下面两篇文章：<br />
1、<span class="a">&nbsp;<span style="font-family: Arial"><a href="http://www.siia.net/software/pubs/SAAS_TCO_WP.pdf">SOFTWARE AS A SERVICE A Comprehensive Look at the Total Cost of Ownership of Software Applications</a> </span><br />
<span style="font-family: Arial">2、<a href="http://msdn2.microsoft.com/en-us/library/aa479069.aspx">Architecture Strategies for Catching the Long Tail</a><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SAAS的三个关键属性：可伸缩性（scalabe），可配置性（configurable）以及面向多用户特性（<em>multi-tenant-efficient</em>），根据这三个特性可以把SAAS的成熟度划分为四种，而ASP可以划分到成熟度1这个层次。</span></span>
</p>

          <br/>
          <span style="color:red;">
            <a href="http://dustin.javaeye.com/blog/98828#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Sat, 07 Jul 2007 17:15:48 +0800</pubDate>
        <link>http://dustin.javaeye.com/blog/98828</link>
        <guid>http://dustin.javaeye.com/blog/98828</guid>
      </item>
      <item>
        <title>Hype Cycle</title>
        <author>Dustin</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://dustin.javaeye.com">Dustin</a>&nbsp;
          链接：<a href="http://dustin.javaeye.com/blog/98238" style="color:red;">http://dustin.javaeye.com/blog/98238</a>&nbsp;
          发表时间: 2007年07月05日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <p>
&nbsp;&nbsp; Hype Cycle是对技术的成熟度，大众接受度和商业应用程度的一个图形化表示。Gartner.com从95年开始每年对相关技术发表相应的Hype Cycle，对当年的各种技术进行评估。通过Hype Cycle，我们可以估计某个技术什么时候会走出所谓&ldquo;盲目的狂热期&rdquo;，最终走向成熟，为大众所接受。横坐标表示技术的成熟度，纵轴表示技术受关注的程度.影响最大的Hype Cycle无疑是99年由<span class="smallGrayText">Alex Drobik 提出的E-Business-Hype Cycle<span class="smallGrayText"> ，因为它准确地预测到了2000年春天</span>dot-com 泡沫的破灭。<br />
</span><a href="http://www.stevenmsmith.com/AYEcon2003/images/GartnerHypeCycle.gif"><img src="http://www.stevenmsmith.com/AYEcon2003/images/GartnerHypeCycle.gif" alt="" /></a><br />
<br />
</p>
<p>
<span style="font-family: Arial"><strong>&nbsp;1. &quot;Technology Trigger&quot;</strong><br />
The first phase of a Hype Cycle is the &quot;technology trigger&quot; or breakthrough, product launch or other event that generates significant press and interest. </span>
</p>
<p>
<span style="font-family: Arial"><strong>2. &quot;Peak of Inflated Expectations&quot;</strong><br />
In the next phase, a frenzy of publicity typically generates over-enthusiasm and unrealistic expectations. There may be some successful applications of a technology, but there are typically more failures. </span>
</p>
<p>
<span style="font-family: Arial"><strong>3. &quot;Trough of Disillusionment&quot;</strong><br />
Technologies enter the &quot;trough of disillusionment&quot; because they fail to meet expectations and quickly become unfashionable. Consequently, the press usually abandons the topic and the technology. </span>
</p>
<p>
<span style="font-family: Arial"><strong>4. &quot;Slope of Enlightenment&quot;</strong><br />
Although the press may have stopped covering the technology, some businesses continue through the &quot;slope of enlightenment&quot; and experiment to understand the benefits and practical application of the technology. </span>
</p>
<p>
<span style="font-family: Arial"><strong>5. &quot;Plateau of Productivity&quot;</strong><br />
A technology reaches the &quot;plateau of productivity&quot; as the benefits of it become widely demonstrated and accepted. The technology becomes increasingly stable and evolves in second and third generations. The final height of the plateau varies according to whether the technology is broadly applicable or benefits only a niche market.&nbsp;<br />
<br />
</span><span style="font-family: Arial">可以看看2005年Gartner发布的Hype Cycle。<br />
<img src="http://multa.murdoch.edu.au/show_image.php?id=20" alt="" /><br />
</span>
</p>

          <br/>
          <span style="color:red;">
            <a href="http://dustin.javaeye.com/blog/98238#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Thu, 05 Jul 2007 21:58:20 +0800</pubDate>
        <link>http://dustin.javaeye.com/blog/98238</link>
        <guid>http://dustin.javaeye.com/blog/98238</guid>
      </item>
      <item>
        <title>How to Ride the Fifth Wave【转】</title>
        <author>Dustin</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://dustin.javaeye.com">Dustin</a>&nbsp;
          链接：<a href="http://dustin.javaeye.com/blog/86353" style="color:red;">http://dustin.javaeye.com/blog/86353</a>&nbsp;
          发表时间: 2007年06月03日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <h1>How to Ride the Fifth Wave</h1>
<div class="storysubhead">
CHEAP COMPUTING, INFINITE BANDWIDTH, AND OPEN STANDARDS ARE POWERING AN EPIC TECHNOLOGICAL TRANSFORMATION THAT WILL CHURN UP HUGE NEW OPPORTUNITIES&mdash;AND PERILS FOR THOSE WHO CAN'T ADAPT.
</div>
<div class="storybyline">
By Michael V. Copeland
</div>
<div class="storytimestamp">
July 1, 2005
</div>
<div class="storytimestamp">
<br />
<a href="http://money.cnn.com/magazines/business2/business2_archive/2005/07/01/8265500/">原文</a>
</div>
<p>
&nbsp;&nbsp;&nbsp; (Business 2.0) &ndash; Rick Rashid makes his living staring off into the distance. He's head of Microsoft Research, the software giant's R&amp;D arm, and it's his job to peer far over the horizon to divine where technology is headed. He ponders out-there issues like what each of us could do if there was enough computer storage to save every conversation we have from birth to death, or what happens when giant LCD panels become as cheap as today's whiteboards. Which makes it slightly incongruous that, at the moment, he's sitting in a Victorian-era hotel talking about steam engines. The setting is San Diego's Hotel del Coronado, built in 1888, and Rashid is explaining how a blast from the past has given him a new notion of the future. On a recent vacation to London, Rashid visited Britain's Science Museum. He lingered before an exhibit of one of James Watt's earliest steam engines and others that followed in various sizes and configurations. It occurred to Rashid that in the 19th century, the answer for every engineering problem was a steam engine. If it was a big problem, it was solved with a big steam engine. Small problem? A small steam engine sufficed. Steam engines were everywhere. The technological muscle they provided sent Britain and ultimately the rest of the world chuffing into the industrial age. 
</p>
<p>
Then it hit him: &quot;I realized that we are coming into a stage now where our version of the steam engine is the microprocessor and software,&quot; Rashid says. &quot;We are getting to a point where it is truly cheap and easy enough to put a combination of processors and software into anything, for any reason.&quot; 
</p>
<p>
Rashid is on to something. We are now in the initial stages of a technological shift that may someday merit its own proud place in the museum. <strong>Roughly speaking, the history of computing has unrolled in four major waves. The first came in the 1960s, as mainframe computers advanced into the corporate world and became essential business tools. The 1970s saw the wide adoption of the minicomputer. Then came the personal computer in the '80s, followed in the '90s by networking and the Internet, and the spread of distributed computing</strong>. Each successive wave of technology brought with it giant leaps in productivity and huge increases in spending. Each transition lifted some companies (think IBM, Microsoft, Yahoo, Google) and swamped those that couldn't adapt (think Wang and Digital Equipment). 
</p>
<p>
<strong>Now comes computing's fifth wave. It's different from the sea changes that came before it. For the first time, the shift isn't driven primarily by a single piece of hardware or by how corporations deploy it. Instead, it results from the unprecedented coalescence of three powerful technological forces: cheap and ubiquitous computing devices, from PCs to cell phones to tiny but potent systems that are beginning to show up in everything from bedroom lamps to key chains; low-cost and omnipresent bandwidth; and open standards&mdash;not just Linux source code but the opening of other software as well as corporate databases. The fifth wave puts computing everywhere. It offers access to limitless amounts of information, services, and entertainment. All the time. Everywhere.</strong> 
</p>
<p>
Best of all, the fifth wave serves as a framework to understand where most of the juiciest opportunities in business are emerging today. It will coincide with, and in some ways fuel, a surprising increase in corporate IT spending. And as the new wave sweeps in, it will create fertile conditions for starting new companies&mdash;even new industries&mdash;and remaking old ones. It won't always be smooth sailing. &quot;It's not going to be this linear progress that we've seen so far,&quot; says Dick Lampman, head of Hewlett-Packard's research labs. &quot;It's this perfect storm of technology rolling in, and it presents thousands of new opportunities to develop devices and services.&quot; For anyone who has ever dreamed of building a game-changing, money-gushing new enterprise, the message is unmistakable: Surf's up. And if you catch it right, the fifth wave could be a mind-blowing ride. 
</p>
<p>
All big technological leaps build on the advances that came before them. Watt's steam engine, for instance, was based on a coal-mining pump designed by the now largely forgotten 18th-century inventor Thomas Newcomen; ultimately it was the combination of the steam engine and that classic of early invention, the wheel, that revolutionized transportation and brought us the industrial age. In the case of the fifth wave, the springboards are a set of familiar but, historically speaking, relatively new technologies that now have matured enough and found a large enough audience to create a wholly new tech terrain. 
</p>
<p>
The Web, of course, is fundamental. In addition, relentless com-modification has driven the cost of computer hardware, and storage in particular, to relative peanuts. Cheap mobile phones and other handhelds now pack as much computing power as workstations did five years ago. More important for the fifth wave, broadband is practically everywhere, and it's blindingly fast. Today's local area networks move data at a gigabit per second. That's a full-length DVD-quality movie every 38 seconds. Wireless technologies, chiefly 3G (third-generation) and Wi-Fi, are expanding rapidly, making the Internet ubiquitous. 
</p>
<p>
A less understood but equally critical development is the spread of technological openness. The open-source movement has created a global tinkerer's workshop, where thousands of creative minds are constantly cobbling together code that entrepreneurs and even established businesses can cannibalize, free of charge, for parts to build new software systems. But fifth-wave pioneers grasp another dimension of technological openness: Many have begun to open up their own databases and software protocols, allowing the tinkerers to create related applications or sell symbiotic products and services. Amazon has taken this approach further than anyone, and Google isn't far behind. (See &quot;The Great Giveaway,&quot; April.) &quot;Open-source changes the rules of the game,&quot; says Tim O'Reilly, founder of tech publishing powerhouse O'Reilly Media. &quot;Anyone can add and innovate, bring new pieces to the party.&quot; 
</p>
<p>
Together these forces have created the technological infrastructure from which the fifth wave is rising. In essence, we are now surrounded by a kind of ecosystem of connectivity, unseen but everywhere, constantly growing, seemingly by itself. One of the distinguishing characteristics of the current shift compared with past ones is how much it is expanding from the grass roots up. Corporations supply some of the momentum, to be sure. But to an unusual degree, consumers are powering the fifth wave, as armies of mobile users discover new ways to exploit the connectivity that surrounds them&mdash;and businesses pop up to cater to them. Downloadable ringtones constitute an industry worth $2 billion a year. Sales of downloadable screensavers for cell phones have gone from basically nonexistent in 2001 to an expected $275 million this year. 
</p>
<p>
There's another singular aspect of what's happening now, one that by itself creates enormous opportunities. A hallmark of the previous four waves was the almost direct correlation between hardware and software. If Intel made a new chip, Microsoft came up with a new operating system that could make use of the extra oomph. The platform and how it could be used basically moved in predictable lockstep. This time, however, the platform&mdash;broadband networks and the Internet&mdash;is already in place, waiting for applications to catch up. 
</p>
<p>
Dozens of fifth-wave companies have been born into that breach. Salesforce.com drew snickers a few years ago when it came up with its model of allowing customers to essentially rent the company's enterprise software over the Web. Among other things, some observers predicted that Salesforce's programs for managing basic business functions like sales and customer service would jam up customers' networks. But because of the growth in bandwidth and cheap storage, that never emerged as a serious issue. Delivery over the Web reduces Salesforce's distribution costs to next to nothing. And the company is sizzling: Its first-quarter profits rose 10-fold year over year to $4.4 million, its revenue jumped 84 percent to $64.2 million, and its stock is up 24 percent this year to about $21 a share. Salesforce is still relatively small, but its impact could be huge: Other software makers, from Siebel to Oracle, have begun to sell programs the same way. &quot;Customers are in open rebellion over the high cost of enterprise software,&quot; says Salesforce CEO Marc Benioff. 
</p>
<p>
Skype, another fifth-wave pathfinder, may similarly transform the phone business by wielding the weapons of cheap computing and bandwidth. Niklas Zennstr&ouml;m and Janus Friis, the brains behind music file-sharing service Kazaa, created Skype in 2003 to provide phone calls over the Web. They spent almost nothing on marketing; the company is basically a roomful of off-the-shelf servers and a tiny peer-to-peer program, downloadable for free from the Web. Skype users can essentially call anywhere in the world to PCs, cell phones, or old-fashioned wired handsets. A half-hour call from, say, San Francisco to London over a Cingular cellular network costs $5.70 or more. On Skype it costs 69 cents&mdash;which is why Skype now has 41 million registered users and is in the process of pulverizing traditional long-distance carriers. 
</p>
<p>
Salesforce and Skype make a lot of noise because of the disruption they're causing to long-standing business models. But there are many other companies flourishing beneath the radar that have even more fully embraced the technological convergence driving the fifth wave. Ambient Devices was founded in 2001 by a group of MIT Media Lab refugees specifically to exploit the fact that it's now cheap and easy to put computing anywhere. And they meant anywhere. Ambient has, for instance, put a computer in a lamp that changes color every time the Nasdaq rises or falls, or when a sunny day turns to rain. 
</p>
<p>
The Cambridge, Mass., startup's combination of software and chipsets allows a wide range of devices to wirelessly pull data from the Internet about weather, traffic, the stock market, and other subjects, and display it as changing colors in a glowing orb or simple movements of a needle against a graphic. In the space of six months before the 2003 Christmas buying season, 10 people at Ambient set up a wireless network that covers 90 percent of the United States, developed a content platform, and manufactured the company's first product, the Orb, to be sold by Neiman Marcus and Brookstone. The clever color-changing object flew off the shelves, and now Ambient products are sold by more than 50 retailers. Ambient won't disclose specific financial figures, but its COO, Nabeel Hyatt, says sales doubled last year and the company is already profitable. 
</p>
<p>
Ambient is a poster-child fifth-wave startup: It used chunks of open-source code as the core of its software. Rather than build its own wireless network, which would have cost hundreds of millions of dollars, Ambient cut a deal with telecom company USA Mobility that let Ambient use existing infrastructure. Data from the Internet was already available, and setting up a Web-based interface for people to program their Ambient toys was a breeze for the MIT brain trust. And since the company is piggybacking on the Internet and an existing wireless network, it can easily scale to millions of customers. &quot;Ultimately we will embed the technology inside all kinds of devices that display information from the Internet for all sorts of manufacturers,&quot; Hyatt says. &quot;It's an incredibly broad opportunity.&quot; 
</p>
<p>
As Ambient illustrates, the ability of a company to easily scale services from a single customer to millions is a defining feature of the fifth wave. Gordon Ritter, a VC at Emergence Capital Partners in San Mateo, Calif., says the secret to doing that is the &quot;Amazon-ification&quot; of software. People tend to think of Amazon as an online store, but it can also be viewed simply as a software platform for delivering a service over the Web. Its interface is customizable down to the individual user, it learns about customers' preferences, and it scales from one person to millions almost effortlessly. Ritter believes all software will soon function that way. 
</p>
<p>
One of Ritter's recent investments is SuccessFactors, which sells subscription-based human resources software heavily underpinned by free open-source code. Success-Factors offers a highly customizable set of HR applications that are accessible using any Web-enabled device. The big shift, Ritter says, has been to design SuccessFactors for millions of individuals rather than taking the traditional approach of tailoring it for specific companies. &quot;It does away with the old schism between the enterprise and consumers,&quot; Ritter says. &quot;It brings service at companies down to the level of individuals in the same way that Amazon does with its customers.&quot; SuccessFactors CEO Lars Dalgaard says he's considering mimicking Amazon further by opening up his company's protocols to anyone who wants to create related services. SuccessFactors's revenue is expected to double this year to $50 million. 
</p>
<p>
By its very nature, the always-connected era creates massive flows of data, and a race is on to develop software systems that help companies deal with it. El Segundo, Calif., startup Siderean Software has created a powerful application designed for needle-in-the-haystack searches of all the data within a corporation, from customer information to radio-frequency tag readouts to e-mail. The software, which contains kernels of open standards, is industrial-strength, but nothing that today's powerhouse corporate servers can't handle. Founder and CTO Bradley Allen says Siderean's software sorts and displays search results in more intuitive and contextual ways than, say, Google. &quot;It's like finding an ethnic restaurant by pinpointing 'restaurant,' 'ethnic,' 'Moroccan,' and 'Fifth Avenue' in a 15-second look at the Manhattan Yellow Pages,&quot; Allen explains, &quot;vs. searching page by page through the White Pages for a week.&quot; 
</p>
<p>
Some of the richest opportunities churned up by the fifth wave are in the tricky but vital need to better merge the computer and the telephone. There remain significant technical hurdles to seamless interaction between the two technologies&mdash;as witnessed by anybody who has had to repeatedly punch in a credit card number to buy something over the phone. In 2000, startup Audium used an open standard called VoiceXML to cook up software that essentially translates voice or data input by punching phone buttons into a digital form readily understood by a corporation's database and other computing systems. Audium is already profitable. Another startup, Transera, has developed software based on free Linux code and other open standards that allows call centers to micromanage incoming calls&mdash;routing particular problems to operators with specific expertise, for instance, and allowing manufacturers to track customer interactions with their offshore support staff in minute detail. &quot;We are marrying the computer to the phone,&quot; says founder and CEO Prem Uppaluru. &quot;A few years ago, this was not even technologically possible.&quot; 
</p>
<p>
Startups aren't the only ones eyeing the onrushing fifth wave. Much of tech's old guard is frantically trying to figure out ways not to get swept away by it&mdash;and some very entrenched companies seem surprisingly well positioned to drop into it and ride. IBM, for instance, has been retooling itself for several years with an eye toward the coming change. Big Blue prefers to call it &quot;on-demand&quot; computing, but however it is described, it's influencing everything CEO Sam Palmisano is doing. The recent sale of IBM's PC division to China-based Lenovo was a highly symbolic clearing of the decks in preparation for focusing intently on the fifth wave. Palmisano also has embraced the open-source movement and poured money into developing Web-enabled services and software. &quot;If you look at all the hot computing trends of the future, IBM suddenly has a very strong foothold in all of them,&quot; says Arnie Berman, senior analyst at CreditSights and an early proponent of the fifth wave. 
</p>
<p>
IBM's approach to the shifting landscape is to retreat from the PC hardware business. But that doesn't mean there's no opportunity for hardware makers. Chipmakers like Intel and AMD essentially see their future not on the desktop but in mobile devices that plug into the new era's all-enveloping connectivity. On a recent afternoon, Fred Weber, AMD's chief technologist, holds up an Audiovox cell phone that sports a mobile Windows operating system and declares, &quot;The action is all here.&quot; AMD still makes the lion's share of its money on processors for PCs, but it has started to roll out chips for smaller, always-on gadgets. &quot;It's mobile, connected devices&mdash;that's where the future lies,&quot; Weber says. Similarly, Cisco, a big fifth-wave adherent, is adjusting to cash in on the trend&mdash;and in many ways already has. As devices proliferate and networks expand, demand for the Cisco switches and routers that connect them and direct Web traffic could explode. And Cisco is expected to rack up $1 billion in sales of Internet phones this year. Says Cisco CTO Charlie Giancarlo, &quot;This shift is going to be monstrous.&quot; 
</p>
<p>
And scary, for those who don't get it. There are already some big tech names that show every sign of wiping out on the fifth wave. America Online (owned by Time Warner, the parent of this magazine) continues to flail, in large part because it has never understood the value of opening up its business the way Amazon and Google have. It remains trapped in its &quot;walled garden&quot;&mdash;and continues to bleed customers. AOL is about to unveil a new public portal that offers more free content, but many experts believe the wave will wash over AOL in the end. Even eBay, an Internet paragon in many ways, has been tentative in opening up its own databases and protocols, a stance that some analysts believe could throttle down its spectacular growth as the technology era shifts. Apple Computer is flying high right now, but given Steve Jobs's legendary resistance to opening up his technology, including the iPod, even Apple could get swamped by the fifth wave. 
</p>
<p>
Over the long haul, one of the most important implications of the fifth wave is that it could create a more level playing field than the tech industry has seen in many years. The old titans may still do well. But many experts believe that the sheer number of opportunities, the cheapness of basic technological components, and the ever lower barriers to entry for many new niches could ring in a golden era for entrepreneurs and upstarts. 
</p>
<p>
iRobot CEO Colin Angle, a man who dreams of putting a robot or three in every home, is one such enthusiast. He has reason to be hopeful these days: iRobot's annual sales are nearing $100 million and jumped 73 percent in 2004. He sees the fifth wave as a mighty equalizer. &quot;If we are willing to envision a ubiquitous network, with ubiquitous storage and computing, that is a world where the Microsoft and Intel platform is not the king anymore,&quot; Angle says. &quot;Innovative entrepreneurs get to play again under this scenario. Stupid, crazy stuff that no legitimate risk-averse company would try gets tried now.&quot; 
</p>
<p>
James Watt could relate. When he first unveiled his steam engine, some of the few people who even knew about it thought he was a fool. That was in 1765. Watt himself had doubts, and took to referring to his soot-belching contraption as &quot;Beelzebub.&quot; But then people began to realize what his technology could enable. Within two decades, Watt's engines were running England's cotton mills. In just a few more came the first steam locomotives, and soon thereafter the world was utterly transformed. The big waves are like that. They can start small, almost unnoticed, but they change the look of everything by the time they break on the beach. 
</p>
<div style="clear: both">
<div id="RelatedStoriesArea">
<!-- BEGIN top stories include -->
</div>
</div>

          <br/>
          <span style="color:red;">
            <a href="http://dustin.javaeye.com/blog/86353#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Sun, 03 Jun 2007 16:31:40 +0800</pubDate>
        <link>http://dustin.javaeye.com/blog/86353</link>
        <guid>http://dustin.javaeye.com/blog/86353</guid>
      </item>
      <item>
        <title>C++的常量</title>
        <author>Dustin</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://dustin.javaeye.com">Dustin</a>&nbsp;
          链接：<a href="http://dustin.javaeye.com/blog/85021" style="color:red;">http://dustin.javaeye.com/blog/85021</a>&nbsp;
          发表时间: 2007年05月31日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <p>
&nbsp;&nbsp; Java里面使用常量十分方便，将成员变量定义为final就行了，但在C++中，类的成员变量是不能赋初值的，因此往往将常量声明为全部数据，并用const来修饰。效果类似，但全局数据往往造成程序间不必要的耦合，是error prone，应该能免则免的。有一个变通的办法就是使用枚举：
</p>
<div class="code_title">
cpp 代码
</div>
<div class="dp-highlighter">
<ol class="dp-cpp">
	<li class="alt"><span><span class="keyword">class</span><span>&nbsp;ConstNum &nbsp;&nbsp;</span></span></li>
	<li><span>{ &nbsp;&nbsp;</span></li>
	<li class="alt"><span>&nbsp;&nbsp;..... &nbsp;&nbsp;</span></li>
	<li><span class="keyword">private</span><span>: &nbsp;&nbsp;</span></li>
	<li class="alt"><span>&nbsp;&nbsp;</span><span class="keyword">enum</span><span>{MAXSIZE=100}; &nbsp;&nbsp;</span></li>
	<li><span>};&nbsp;&nbsp;</span></li>
</ol>
</div>
&nbsp; 还有一种方法使用静态类变量<br />
<div class="code_title">
cpp 代码
</div>
<div class="dp-highlighter">
<ol class="dp-cpp">
	<li class="alt"><span><span class="keyword">class</span><span>&nbsp;ConstNum &nbsp;&nbsp;</span></span></li>
	<li><span>{ &nbsp;&nbsp;</span></li>
	<li class="alt"><span>..... &nbsp;&nbsp;</span></l