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

<channel>
	<title>Some reminiscences, some memories &#187; 性能</title>
	<atom:link href="http://www.mikespook.com/index.php/tag/%e6%80%a7%e8%83%bd/feed" rel="self" type="application/rss+xml" />
	<link>http://www.mikespook.com</link>
	<description>Just another boring day</description>
	<lastBuildDate>Tue, 10 Jan 2012 03:14:06 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>[翻译]Goroutine性能测试</title>
		<link>http://www.mikespook.com/2012/01/goroutine%e6%80%a7%e8%83%bd%e6%b5%8b%e8%af%95/</link>
		<comments>http://www.mikespook.com/2012/01/goroutine%e6%80%a7%e8%83%bd%e6%b5%8b%e8%af%95/#comments</comments>
		<pubDate>Fri, 06 Jan 2012 03:55:10 +0000</pubDate>
		<dc:creator>mikespook</dc:creator>
				<category><![CDATA[Golang]]></category>
		<category><![CDATA[golang]]></category>
		<category><![CDATA[goroutine]]></category>
		<category><![CDATA[性能]]></category>
		<category><![CDATA[翻译]]></category>

		<guid isPermaLink="false">http://www.mikespook.com/?p=1177</guid>
		<description><![CDATA[<style type="text/css">
#leftcontainerBox {
	float:left;
	position: fixed;
	top: 60%;
	left: 70px;
}
#leftcontainerBox .buttons {
	float:left;
	clear:both;
	margin:4px 4px 4px 4px;
	padding-bottom:2px;
}
#bottomcontainerBox {
	width: 50%;
	padding-top: 1px;
}
#bottomcontainerBox .buttons {
	float: left;
	margin: 4px 4px 4px 4px;
}
</style>
原文在此：http://en.munknex.net/2011/12/golang-goroutines-performance.html

&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;翻译分割线&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;

概述

<span class="readmore"><a href="http://www.mikespook.com/2012/01/goroutine%e6%80%a7%e8%83%bd%e6%b5%8b%e8%af%95/" title="[翻译]Goroutine性能测试">阅读全文——共1952字</a></span>]]></description>
			<content:encoded><![CDATA[<style type="text/css">
#leftcontainerBox {
	float:left;
	position: fixed;
	top: 60%;
	left: 70px;
}
#leftcontainerBox .buttons {
	float:left;
	clear:both;
	margin:4px 4px 4px 4px;
	padding-bottom:2px;
}
#bottomcontainerBox {
	width: 50%;
	padding-top: 1px;
}
#bottomcontainerBox .buttons {
	float: left;
	margin: 4px 4px 4px 4px;
}
</style>
<p>原文在此：<a href="http://en.munknex.net/2011/12/golang-goroutines-performance.html" target="_blank">http://en.munknex.net/2011/12/golang-goroutines-performance.html</a></p>
<p>&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;翻译分割线&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;</p>
<h1>概述</h1>
<p>在这篇文章里，我将尝试评估 goroutine 的性能。goroutine 是类似轻量级线程的东西。为了提供原生的多任务，它（协同 channel 一起）被内建于Go中。</p>
<p>文档告诉我们：</p>
<blockquote><p>它实际上是在同一个地址空间里创建成百上千个 goroutine。</p></blockquote>
<p>因此，这个文章的重点就是测试并明确在如此巨大的并发运行函数的情况下所能承受的性能压力上限。<br />
<span id="more-1177"></span></p>
<h1>内存</h1>
<p>创建一个新的goroutine所需空间并未记录在文档中。只是说需要几千字节。在不同的机制下测试，帮助确认这个数值为4—4.5kB。因此，5GB差不多足够运行一百万个goroutine。</p>
<h1>性能</h1>
<p>让我们算算在一个 goroutine 里运行函数会损失多少的性能吧。可能你已经知道这非常简单——只要在函数调用前添加 go 关键字：</p>
<pre class="brush: cpp; title: ; notranslate">
go testFunc()
</pre>
<p>goroutine 复用于线程。默认情况下，如果没有设定 GOMAXPROCS 环境变量，程序只使用一个线程。为了利用全部 CPU 内核，则必须制定它的值。例如：</p>
<pre class="brush: bash; title: ; notranslate">
export GOMAXPROCS=2
</pre>
<p>这个值在运行时使用。因此没有必要在每次修改这个值之后，重新编译程序。</p>
<p>以我的推断，大多数时间花费在创建 goroutine，切换它们，以及从一个线程迁移 goroutine 到另外的线程，还有在不同的线程之间的 goroutine 进行通讯。为了避免无尽的论述，让我们从仅用一个线程的情况开始。</p>
<p>所有测试都是在我的 nettop（译注：英特尔公司的低成本简易台式机解决方案）上完成的：</p>
<ul>
<li>Atom D525 Dual Core 1.8 GHz</li>
<li>4Gb DDR3</li>
<li>Go r60.3</li>
<li>Arch Linux x86_64</li>
</ul>
<h1>方法</h1>
<p>这是测试函数生成器：</p>
<pre class="brush: cpp; title: ; notranslate">
func genTest (n int) func (res chan &lt;- interface {}) {
        return func(res chan &lt;- interface {}) {
                for i := 0; i &lt; n; i++ {
                        math.Sqrt(13)
                }
                res &lt;- true
        }
}
</pre>
<p>然后这里是一系列分别计算 sqrt(13) 1、10、100、1000 和 5000 次的函数集合：</p>
<pre class="brush: cpp; title: ; notranslate">
testFuncs := [] func (chan &lt;- interface {}) { genTest(1), genTest(10), genTest(100), genTest(1000), genTest(5000) }
</pre>
<p>我将每个函数在循环中执行 X 遍，然后在 goroutine 中执行 X 遍。然后比较结果。当然，应当留意垃圾回收。为了降低其带来的影响，我在 goroutine 结束后显式调用了 runtime.GC() 并记录结束时间。当然，为了测试精确性，每个测试执行了许多遍。整个运行时间用了大约 16 小时。</p>
<h1>一个线程</h1>
<pre class="brush: bash; title: ; notranslate">
export GOMAXPROCS=1
</pre>
<p><img src="https://lh4.googleusercontent.com/-tJyRcozfSi4/Tv4c-32C8LI/AAAAAAAABmw/2eBz0cWFWaw/s980/BOlyT.png" alt="goroutine 性能测试 1.1" /></p>
<p>图表显示在 goroutine 中运行的 sqrt() 计算工作大约比在函数中运行慢四倍。</p>
<p>来看看剩余的四个函数的情况：</p>
<p><img src="https://lh3.googleusercontent.com/-SdI6VAsosG0/Tv4c9x9NpDI/AAAAAAAABmo/c6EVJs4scHY/s983/bdJiZ.png" alt="goroutine 性能测试 1.2" /></p>
<p>你会注意到，即使并发执行70万 goroutine 也不会使得性能下降到 80% 以下。现在是最值得敬佩的地方。从 sqrt()x1000 开始，总体消耗低于 2%。5000 次——只有 1%。看起来这个数值与 goroutine 的数量无关！因此唯一的制约因素是内存。</p>
<h1>概要：</h1>
<p>如果互不依赖的代码的执行时间高于计算平方跟的10倍，并且你希望它并发执行，应毫不犹豫的让其在 goroutine 中运行。虽然，可以轻松的将10或者100个这样的代码放在一起，不过损失的性能仅仅分别是 20% 和 2%。</p>
<h1>多线程</h1>
<p>现在来看看当我们希望使用若干个处理器内核时的情况。在我的用例中是 2 个：</p>
<pre class="brush: bash; title: ; notranslate">
export GOMAXPROCS=2
</pre>
<p>再次执行我们的测试程序：</p>
<p><img src="https://lh3.googleusercontent.com/--Oopi4ZD_BU/Tv4c8s6C7JI/AAAAAAAABmg/i6I2GFF6JeI/s977/zcv7K.png" alt="goroutine 性能测试 2.1" /></p>
<p>这里你会发现，尽管内核数增加了一倍，但是前两个函数的运行时间却增加了！这极可能是在线程之间移动比执行它们的开销要大得多。：）当前的调度器还不能处理，不过 Go 的开发者承诺在未来会解决这种情况。</p>
<p><img src="https://lh4.googleusercontent.com/-f7R2zsoajNI/Tv4c7W6Um4I/AAAAAAAABmY/qY6C6eYQOzI/s981/Jp3lZ.png" alt="goroutine 性能测试 2.2" /></p>
<p>你已经看到了，最后的两个函数完全使用了两个核。在我的 nettop 上，他们的执行时间分别是 ~45µs 和 ~230µs。</p>
<h1>总结</h1>
<p>尽管这是一个年轻的语言，并且有着一个临时的调度器实现，goroutine 的性能让人觉得兴奋。尤其是与 Go 的简单易用结合起来的时候。这令我印象深刻。感谢 Go 开发团队！</p>
<p>当运行时间少于 1µs 我会在执行 goroutine 之前深思熟虑一下，而如果运行时间超过 1ms，那就决不犹豫的使用 goroutine 了。：）</p>
]]></content:encoded>
			<wfw:commentRss>http://www.mikespook.com/2012/01/goroutine%e6%80%a7%e8%83%bd%e6%b5%8b%e8%af%95/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>[翻译]Go 和 Python 的 Web 服务器性能对比</title>
		<link>http://www.mikespook.com/2011/02/%e7%bf%bb%e8%af%91go-%e5%92%8c-python-%e7%9a%84-web-%e6%9c%8d%e5%8a%a1%e5%99%a8%e6%80%a7%e8%83%bd%e5%af%b9%e6%af%94/</link>
		<comments>http://www.mikespook.com/2011/02/%e7%bf%bb%e8%af%91go-%e5%92%8c-python-%e7%9a%84-web-%e6%9c%8d%e5%8a%a1%e5%99%a8%e6%80%a7%e8%83%bd%e5%af%b9%e6%af%94/#comments</comments>
		<pubDate>Thu, 24 Feb 2011 04:46:27 +0000</pubDate>
		<dc:creator>mikespook</dc:creator>
				<category><![CDATA[Python]]></category>
		<category><![CDATA[Stardy & Research]]></category>
		<category><![CDATA[Go]]></category>
		<category><![CDATA[web]]></category>
		<category><![CDATA[性能]]></category>

		<guid isPermaLink="false">http://www.mikespook.com/?p=857</guid>
		<description><![CDATA[<style type="text/css">
#leftcontainerBox {
	float:left;
	position: fixed;
	top: 60%;
	left: 70px;
}
#leftcontainerBox .buttons {
	float:left;
	clear:both;
	margin:4px 4px 4px 4px;
	padding-bottom:2px;
}
#bottomcontainerBox {
	width: 50%;
	padding-top: 1px;
}
#bottomcontainerBox .buttons {
	float: left;
	margin: 4px 4px 4px 4px;
}
</style>
原文在此：http://ziutek.github.com/web_bench/

由于是早上看到 鱼哥，在推上的推荐，我实在忍不住……这是中午的草率之举，所以 鱼哥 对本文的翻译负全责。

PS：别说我工作状态不饱满，我在等丫的程序执行完……

<span class="readmore"><a href="http://www.mikespook.com/2011/02/%e7%bf%bb%e8%af%91go-%e5%92%8c-python-%e7%9a%84-web-%e6%9c%8d%e5%8a%a1%e5%99%a8%e6%80%a7%e8%83%bd%e5%af%b9%e6%af%94/" title="[翻译]Go 和 Python 的 Web 服务器性能对比">阅读全文——共2501字</a></span>]]></description>
			<content:encoded><![CDATA[<style type="text/css">
#leftcontainerBox {
	float:left;
	position: fixed;
	top: 60%;
	left: 70px;
}
#leftcontainerBox .buttons {
	float:left;
	clear:both;
	margin:4px 4px 4px 4px;
	padding-bottom:2px;
}
#bottomcontainerBox {
	width: 50%;
	padding-top: 1px;
}
#bottomcontainerBox .buttons {
	float: left;
	margin: 4px 4px 4px 4px;
}
</style>
<p>原文在此：<a href="http://ziutek.github.com/web_bench/" target="_blank">http://ziutek.github.com/web_bench/</a></p>
<p>由于是早上看到 <a href="https://twitter.com/smallfish_xy" target="_blank">鱼哥</a>，在推上的推荐，我实在忍不住……这是中午的草率之举，所以 <a href="https://twitter.com/smallfish_xy" target="_blank">鱼哥</a> 对本文的翻译负全责。</p>
<p>PS：别说我工作状态不饱满，我在等丫的程序执行完……</p>
<p>&#8212;&#8212;&#8212;&#8212;翻译分割线&#8212;&#8212;&#8212;&#8212;</p>
<h1>Go 和 Python Web 服务器性能对比</h1>
<p>我通常使用 <a href="http://www.python.org/">Python</a> 来构建 Web 应用。一年前，在兴趣的驱使下，我开始学习 <a href="http://golang.org/">Go</a>。 在此期间，我重写了一些原本由 C 开发的 CGI 应用，包括运行于 <a href="http://en.wikipedia.org/wiki/Chroot">chroot</a> 环境下的同 <a href="http://www.acme.com/software/thttpd/">thttpd</a> 服务器一起的应用。我开始寻找可以开发易于 chroot、且内置 Web 服务器的独立 Web 应用的工具。那时，我开始玩 <a href="http://www.getwebgo.com/">web.go</a> 框架、<a href="https://github.com/hoisie/mustache.go">mustache.go</a> 模板、Go 原生 <a href="http://golang.org/pkg/http/">http</a> 包和 <a href="https://github.com/Philio/GoMySQL">GoMySQL</a> 数据库 API。我发现，有 http、mustache.go  GoMySQL 包的 Go 可以是我用来工作的不错的工具组合。因此，我决定使用 Go 编写我的应用。<br />
<span id="more-857"></span><br />
在工作过程中发现，我需要比 mustache.go 更加灵活，比 GoMySQL 更加成熟、没有那么多 Bug 的东西。最终，我使用 <a href="https://github.com/ziutek/kasia.go">Kasia.go</a> 模板和  <a href="https://github.com/ziutek/mymysql">MyMySQL</a> （为我的应用定制开发的包，不过我将其贡献给了 Go 社区）。重写的应用即便是在比以前的负载更高的运营环境下，也工作得很好。我开始思考这个问题：用 Go 实现独立 Web 应用比 Python 到底快了（或者是慢了）多少。我决定做一些各种框架和服务器不同的用途的测试。为了比较，我选择了下面的 Go 包：</p>
<ul>
<li>原始的 Go http包；</li>
<li>web.go 框架（它使用运行于独立模式[standalone mode] 的 http 包）；</li>
<li><a href="http://garyburd.github.com/twister/">twister</a> 框架 （它同样使用 http 包）。</li>
</ul>
<p>和下面的 Python Web服务器/框架：</p>
<ul>
<li>使用 <a href="http://www.cherrypy.org/">CherryPy</a> WSGI 服务器的<a href="http://webpy.org/"> web.py</a> 框架；</li>
<li>使用 <a href="http://trac.saddi.com/flup">flup</a> <a href="http://en.wikipedia.org/wiki/FastCGI">FastCGI</a> 做 <a href="http://wiki.nginx.org/Main">nginx</a> 服务器的后台处理的 web.py 框架；</li>
<li><a href="http://www.tornadoweb.org/">tornado</a> 异步服务器/框架；</li>
<li>nginx 做负载均衡的 tornado。</li>
</ul>
<p>每一个用例，我都编写了一个小应用，略微复杂一些的、传统的 Hello World 例子。任何应用都包括：</p>
<ul>
<li>使用正则表达式通过 URL 路径传递参数；</li>
<li>使用语句创建多行输出；</li>
<li>使用 printf 形式的格式化函数/表达式格式化输出。</li>
</ul>
<p>我想，这些都是在 Web 应用中常见的操作，所以应当包含在任何简易的性能对比测试中。所有测试应用的代码在下面的链接中：</p>
<ul>
<li> <a href="https://github.com/ziutek/web_bench/blob/master/http.go">Go http</a></li>
<li> <a href="https://github.com/ziutek/web_bench/blob/master/webgo.go">web.go</a></li>
<li> <a href="https://github.com/ziutek/web_bench/blob/master/twister.go">twister</a></li>
<li> <a href="https://github.com/ziutek/web_bench/blob/master/webpy.py">web.py</a></li>
<li> <a href="https://github.com/ziutek/web_bench/blob/master/trnado.py">tornado</a></li>
</ul>
<h2>测试环境</h2>
<p>测试环境包括两台 使用千兆以太网链接的PC （请求发起者和应用服务器）。</p>
<ul>
<li>请求发起者：2 x Xeon 2.6 GHz with hyperthreading, Debian SID,     kernel: 2.6.33.7.2-rt30-1-686 #1 SMP PREEMPT RT；</li>
<li>服务器: MSI Netbook with two core Intel U4100 1.30GHz, AC power     connected, 64-bit Ubuntu 10.10, kernel: 2.6.35-25-generic #44-Ubuntu SMP,     Python 2.6.6-2ubuntu2, web.py 0.34-2, flup 1.0.2-1, tornado 0.2-1, nginx     0.7.67-3ubuntu1；</li>
</ul>
<p>为了产生 HTTP 请求并且评估测试应用的性能，我使用 <a href="http://www.joedog.org/index/siege-home">siege</a> 性能测试工具。Siege 可以用多线程模拟多个用户。我使用了下面的命令产生请求：</p>
<pre class="brush: bash; title: ; notranslate">siege -c 200 -t 20s http://SERVER_ADDR:8080/Hello/100</pre>
<p>或者多个类似的命令，减少参数 -c 的量（在这个测试中，我同时运行了多个 Python 脚本）。它模拟了 200 用户的请求，并持续 20 秒。这个 URL 使得 Web 应用对每个请求都输出 100 行。Go 应用使用 Go 发布版 2011-02-01.1。</p>
<h2>结果</h2>
<p>GOMAXPROCS=1, 一个 Python 进程：</p>
<table style="border: 1px solid;">
<tbody>
<tr>
<th>框架</th>
<th colspan="2">请求速率 [1/sec]</th>
</tr>
<tr>
<td>Go http</td>
<td>1350</td>
<td></td>
</tr>
<tr>
<td>Twister</td>
<td>1324</td>
<td></td>
</tr>
<tr>
<td>Web.go</td>
<td>1141</td>
<td></td>
</tr>
<tr>
<td>Tornado</td>
<td>882</td>
<td></td>
</tr>
<tr>
<td>Tornado+nginx</td>
<td>862</td>
<td></td>
</tr>
<tr>
<td>Web.py+CheryPy</td>
<td>169</td>
<td></td>
</tr>
<tr>
<td>Web.py+nginx</td>
<td>114</td>
<td></td>
</tr>
</tbody>
</table>
<p>GOMAXPROCS=2, 两个 Python 并发进程：</p>
<table style="border: 1px solid;">
<tbody>
<tr>
<th>框架</th>
<th colspan="2">请求速率 [1/sec]</th>
</tr>
<tr>
<td>Go http</td>
<td>1768</td>
<td></td>
</tr>
<tr>
<td>Twister</td>
<td>1746</td>
<td></td>
</tr>
<tr>
<td>Tornado</td>
<td>1682</td>
<td></td>
</tr>
<tr>
<td>Web.go</td>
<td>1516</td>
<td></td>
</tr>
<tr>
<td>Tornado+nginx</td>
<td>1378</td>
<td></td>
</tr>
<tr>
<td>Web.py+CheryPy</td>
<td>308</td>
<td></td>
</tr>
<tr>
<td>Web.py+nginx</td>
<td>198</td>
<td></td>
</tr>
</tbody>
</table>
<p>GOMAXPROCS=4, 四个 Python 并发进程：</p>
<table style="border: 1px solid;">
<tbody>
<tr>
<th>框架</th>
<th colspan="2">请求速率 [1/sec]</th>
</tr>
<tr>
<td>Go http</td>
<td>2063</td>
<td></td>
</tr>
<tr>
<td>Twister</td>
<td>2020</td>
<td></td>
</tr>
<tr>
<td>Web.go</td>
<td>1753</td>
<td></td>
</tr>
<tr>
<td>Tornado</td>
<td>1662</td>
<td></td>
</tr>
<tr>
<td>Tornado+nginx</td>
<td>1364</td>
<td></td>
</tr>
<tr>
<td>Web.py+CheryPy</td>
<td>304</td>
<td></td>
</tr>
<tr>
<td>Web.py+nginx</td>
<td>211</td>
<td></td>
</tr>
</tbody>
</table>
<p>Web.py+nginx 工作的 flup FastCGI 选项：multiplexed=False, multithreaded=False。如果 multiplexed=True 它会运行得慢一些。如果 multithreaded=True 而只有一个进程服务于 nginx 服务器，会报下面的错误：</p>
<pre class="brush: bash; title: ; notranslate">[error] 18166#0: *66139 connect() to
unix:/home/michal/Programowanie/web_bench/socket failed (11: Resource
temporarily unavailable) while connecting to upstream</pre>
<p>FastCGI 的多进程由 <a href="http://redmine.lighttpd.net/projects/spawn-fcgi/wiki">spawn-fcgi</a> 产生。</p>
<h2>结论</h2>
<p>你可以看到 Go 赢得了几乎所有的测试用例。web.go 框架的那个不太理想的结果可能是由于它先尝试用指定的 URL 寻找静态页面，然后才会执行处理方法。让我惊讶的是 tornado Python 框架如此之高的性能，尤其是跟 web.py 框架相比而言。我同样对 CherryPy 服务器比 nginx+flup 快感到惊讶 (我使用 web.py+flup+nginx 跑几乎所有的 Python Web 应用)。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.mikespook.com/2011/02/%e7%bf%bb%e8%af%91go-%e5%92%8c-python-%e7%9a%84-web-%e6%9c%8d%e5%8a%a1%e5%99%a8%e6%80%a7%e8%83%bd%e5%af%b9%e6%af%94/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>Mysql 性能改进——最快实践</title>
		<link>http://www.mikespook.com/2009/06/mysql-%e6%80%a7%e8%83%bd%e6%94%b9%e8%bf%9b%e2%80%94%e2%80%94%e6%9c%80%e5%bf%ab%e5%ae%9e%e8%b7%b5/</link>
		<comments>http://www.mikespook.com/2009/06/mysql-%e6%80%a7%e8%83%bd%e6%94%b9%e8%bf%9b%e2%80%94%e2%80%94%e6%9c%80%e5%bf%ab%e5%ae%9e%e8%b7%b5/#comments</comments>
		<pubDate>Mon, 29 Jun 2009 05:10:01 +0000</pubDate>
		<dc:creator>mikespook</dc:creator>
				<category><![CDATA[Database]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[优化]]></category>
		<category><![CDATA[性能]]></category>

		<guid isPermaLink="false">http://www.mikespook.com/?p=361</guid>
		<description><![CDATA[<style type="text/css">
#leftcontainerBox {
	float:left;
	position: fixed;
	top: 60%;
	left: 70px;
}
#leftcontainerBox .buttons {
	float:left;
	clear:both;
	margin:4px 4px 4px 4px;
	padding-bottom:2px;
}
#bottomcontainerBox {
	width: 50%;
	padding-top: 1px;
}
#bottomcontainerBox .buttons {
	float: left;
	margin: 4px 4px 4px 4px;
}
</style>
没错，标题我没打错。这里不是最佳实践，而是最快实践。在服务器上线，巨大的压力导致相应缓慢的时候，最佳实践已经毫无意义。这个时候，目的只有一个：最快改善性能，给开发人员重新设计、调整应用留出一定的时间。

这里不是细腻的微调，而是最粗旷的拉升。用最简单（可快速实施），变更最少（尽量避免变更引入新的 bug 和问题）的方法迅速改善 mysql 的性能。所以我这里的最快实践，不一定是最好的，不一定是最有效的，但是一定是最快能看到性能改善的方法。

tmp_table_size

<span class="readmore"><a href="http://www.mikespook.com/2009/06/mysql-%e6%80%a7%e8%83%bd%e6%94%b9%e8%bf%9b%e2%80%94%e2%80%94%e6%9c%80%e5%bf%ab%e5%ae%9e%e8%b7%b5/" title="Mysql 性能改进——最快实践">阅读全文——共1489字</a></span>]]></description>
			<content:encoded><![CDATA[<style type="text/css">
#leftcontainerBox {
	float:left;
	position: fixed;
	top: 60%;
	left: 70px;
}
#leftcontainerBox .buttons {
	float:left;
	clear:both;
	margin:4px 4px 4px 4px;
	padding-bottom:2px;
}
#bottomcontainerBox {
	width: 50%;
	padding-top: 1px;
}
#bottomcontainerBox .buttons {
	float: left;
	margin: 4px 4px 4px 4px;
}
</style>
<p>没错，标题我没打错。这里不是最佳实践，而是最快实践。在服务器上线，巨大的压力导致相应缓慢的时候，最佳实践已经毫无意义。这个时候，目的只有一个：最快改善性能，给开发人员重新设计、调整应用留出一定的时间。</p>
<p>这里不是细腻的微调，而是最粗旷的拉升。用最简单（可快速实施），变更最少（尽量避免变更引入新的 bug 和问题）的方法迅速改善 mysql 的性能。所以我这里的最快实践，不一定是最好的，不一定是最有效的，但是一定是最快能看到性能改善的方法。<span id="more-361"></span></p>
<h1>tmp_table_size</h1>
<p>实施难度：容易</p>
<p>实施时间：短</p>
<p>实施效果：明显</p>
<p>tmp_table_size 默认 32M，根据手册上的说法，这个限制了内存临时表的大小。增大这个值可以立刻改善 mysql 的性能，虽然不是万灵丹，但却是个救命药。网上解释很多不多说了。</p>
<h1>thread_cache_size</h1>
<p>实施难度：容易</p>
<p>实施时间：短</p>
<p>实施效果：一般</p>
<p>在使用 SHOW STATUS; 查看 mysql 参数时，如果 thread_created 这个值很高的话，可以将 thread_cache_size 设置得大一些。内存允许的情况下，128 或者更大都是可以考虑的。mysql 通过内建的线程复用机制来实现了一个连接池。如果你的应用出现 max connection 的情况话（php 发生这种情况尤为严重），还是请开启 thread_cache_size 吧。</p>
<h1>索引</h1>
<p>实施难度：一般</p>
<p>实施时间：一般</p>
<p>实施效果：明显</p>
<p>不知什么时候，有一位高人说“对于 where 查询的条件字段，都加上索引会提高查询效率”。于是大家忙不停的将所有可能的字段都加上了索引。潘多拉的魔盒从此打开……</p>
<p>上图：</p>
<p><a href="http://www.mikespook.com/wp-content/uploads/2009/06/nouse_index.JPG"><img class="size-full wp-image-362 alignnone" title="nouse_index" src="http://www.mikespook.com/wp-content/uploads/2009/06/nouse_index.JPG" alt="nouse_index" width="554" height="114" /></a></p>
<p>这样的表中，假设 t2 的总记录数不超过10 条。如果 t2_c1 这个字段有这样的查询 select * from t1 where t2_c1 = 1; 不少童鞋都会在 t2_c1 上加多一个索引，为了让这个搜索更快一些。这会是真的么？</p>
<p>显然不是！</p>
<p>在 t2_c1 字段的数据差异很小的情况下，使用索引不会比全表扫描快。更有可能的情况是，索引不但导致 t1 表数据修改变慢，同时导致查询变慢。为什么？大家先学习一下“随机存取”和“连续预读”的差异就明白了。不必要的索引还是去掉吧！我甚至见过索引比数据都大的表，如果读索引的速度比直接读数据都慢，这会有什么后果？太可怕了……</p>
<h1>只查要用到的列</h1>
<p>实施难度：大</p>
<p>实施时间：长</p>
<p>实施效果：明显</p>
<p>这绝对是老生常谈，但是总有人不在意。他们心中有疑问：“为什么？为什么？为什么 SELECT * FROM table 会慢？”他们心中有梦想：“这不可能吧，扫描的都是那么多数据，那几个表。索引使用也一样有效。”</p>
<p>的确，数据扫描的记录数不会因为列的限制而减少，索引的影响也不因为列的限制而改变。不过每个内存页面中存放记录的条数会因为列的不同发不同。为了说明这个问题，我专门构造了一个 140万条记录，每条记录大约 50字节的表。如果应用只是用结果集的主键，使用 select * from table 查询比使用 select id from table 慢了近一倍。其实道理也很简单，结果集行记录变小了，内存页面中每个页面可以放的记录数就多了。内存页面的交换就减少，I/O减少。同时采用连续预读I/O效率提高。进而查询速度提升。</p>
<p>在业务逻辑都确定的情况下，每个方法所用到的字段也都确定了。这个时候可以快速将那些没有用到的字段从查询语句中剔除。查询效率自然提升。</p>
<p>按照上面的顺序进行快速优化，可以在不改变业务逻辑和代码逻辑的情况下迅速提升 mysql 性能，同时可避免应用长时间下下线，也为进一步优化争取时间。何乐而不为？</p>
<p>如果还有更快、更好的方法，我再补充吧！</p>
<p><strong>“性能是改进出来的，不是设计出来的！”</strong></p>
]]></content:encoded>
			<wfw:commentRss>http://www.mikespook.com/2009/06/mysql-%e6%80%a7%e8%83%bd%e6%94%b9%e8%bf%9b%e2%80%94%e2%80%94%e6%9c%80%e5%bf%ab%e5%ae%9e%e8%b7%b5/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>关于 web game 运算负载的只言片语</title>
		<link>http://www.mikespook.com/2009/01/%e5%85%b3%e4%ba%8e-web-game-%e8%bf%90%e7%ae%97%e9%99%84%e5%9c%a8%e7%9a%84%e5%8f%aa%e8%a8%80%e7%89%87%e8%af%ad/</link>
		<comments>http://www.mikespook.com/2009/01/%e5%85%b3%e4%ba%8e-web-game-%e8%bf%90%e7%ae%97%e9%99%84%e5%9c%a8%e7%9a%84%e5%8f%aa%e8%a8%80%e7%89%87%e8%af%ad/#comments</comments>
		<pubDate>Thu, 08 Jan 2009 14:50:31 +0000</pubDate>
		<dc:creator>mikespook</dc:creator>
				<category><![CDATA[Game]]></category>
		<category><![CDATA[webgame]]></category>
		<category><![CDATA[性能]]></category>

		<guid isPermaLink="false">http://www.mikespook.com/index.php/archives/274</guid>
		<description><![CDATA[<style type="text/css">
#leftcontainerBox {
	float:left;
	position: fixed;
	top: 60%;
	left: 70px;
}
#leftcontainerBox .buttons {
	float:left;
	clear:both;
	margin:4px 4px 4px 4px;
	padding-bottom:2px;
}
#bottomcontainerBox {
	width: 50%;
	padding-top: 1px;
}
#bottomcontainerBox .buttons {
	float: left;
	margin: 4px 4px 4px 4px;
}
</style>
没办法整理成长篇大论了，就写点只言片语吧。

起因看这里：http://www.javaeye.com/topic/305801?page=1

 －－－－－－－－－－－－－－－－－

<span class="readmore"><a href="http://www.mikespook.com/2009/01/%e5%85%b3%e4%ba%8e-web-game-%e8%bf%90%e7%ae%97%e9%99%84%e5%9c%a8%e7%9a%84%e5%8f%aa%e8%a8%80%e7%89%87%e8%af%ad/" title="关于 web game 运算负载的只言片语">阅读全文——共885字</a></span>]]></description>
			<content:encoded><![CDATA[<style type="text/css">
#leftcontainerBox {
	float:left;
	position: fixed;
	top: 60%;
	left: 70px;
}
#leftcontainerBox .buttons {
	float:left;
	clear:both;
	margin:4px 4px 4px 4px;
	padding-bottom:2px;
}
#bottomcontainerBox {
	width: 50%;
	padding-top: 1px;
}
#bottomcontainerBox .buttons {
	float: left;
	margin: 4px 4px 4px 4px;
}
</style>
<p>没办法整理成长篇大论了，就写点只言片语吧。<br />
起因看这里：<a href="http://www.javaeye.com/topic/305801?page=1" target="_blank">http://www.javaeye.com/topic/305801?page=1<br />
</a> －－－－－－－－－－－－－－－－－<br />
看了一遍，忍不住了，插句嘴～～</p>
<p>webgame 根本没有，也不需要什么大量实时数据要处理～～</p>
<p>例如类似部落战争的行军，这个其实早就根据所选兵种、指挥官、宝物等等生成了一个事件存放在事件队列中（可能是内存对象、可能是某种数据缓存更有可能是数据库的某条记录），然后服务器在那个事件事件到达的时候取出事件对象执行一下，得到一个结果，接着存起来。至于行军途中到哪个位置如何如何，那是给玩家想象的，服务器根本不管。总之，事件运算有三种方式：1。玩家请求时已经运算完成，到了特定时间通知玩家。2。事件执行时间运算完成，并通知玩家。3。在服务器空闲时，处理待处理的运算，到了特定时间通知玩家。</p>
<p>webgame， MMO 实时性不是首先考虑的。例如资源增长，如果服务器有 10W 激活用户，在同一时间增长资源是几乎不可能的。那就将一分钟划分60秒（废话），每秒开一个新线程来处理一部分用户（10W/60）的资源增长。资源增长基本上就是浮点数加减乘除，对于现在的 cpu 来说，并不是很高。何况服务器 N 个 cpu……</p>
<p>简单的说，webgame 不像 MMO 需要“随时”客户端跟服务器端通讯。更多情况，web 服务器通过某种方式从 game server 中获得一个当前游戏状态的快照返回到浏览器。并从浏览器接收数据，然后在一个可接受的，合理的时间内去修改 game server 的状态。请再次注意，again！这不是“实时”的！</p>
<p>最后再罗嗦一下，webgame 的 game server 更多情况下是一个 task server。它不需要去预测客户端行为，也不需要计算碰撞、寻找可行路径……<br />
另外，我个人的体会，RPG 类型的 webgame 在运算负载上来说，远小于策略形的。并且通常只需要 3 台服务器配合：web server、task server、db server。</p>
<p>哦，还有，如果用 flash 的 socket 方式开发，不在上述范围内。当这种模式是个客户端能力稍差的 MMO 好了。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.mikespook.com/2009/01/%e5%85%b3%e4%ba%8e-web-game-%e8%bf%90%e7%ae%97%e9%99%84%e5%9c%a8%e7%9a%84%e5%8f%aa%e8%a8%80%e7%89%87%e8%af%ad/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
	</channel>
</rss>

