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

<channel>
	<title>Tim[后端技术] &#187; Lua</title>
	<atom:link href="http://timyang.net/category/lua/feed/" rel="self" type="application/rss+xml" />
	<link>http://timyang.net</link>
	<description>Tim&#039;s blog, 关于后端架构、互联网技术、分布式、大型网络应用、NoSQL、Key Value等</description>
	<lastBuildDate>Mon, 26 Jul 2010 15:32:05 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.1</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Lua coroutine vs Java wait/notify</title>
		<link>http://timyang.net/lua/lua-coroutine-vs-java-wait-notify/</link>
		<comments>http://timyang.net/lua/lua-coroutine-vs-java-wait-notify/#comments</comments>
		<pubDate>Mon, 27 Apr 2009 14:39:07 +0000</pubDate>
		<dc:creator>Tim</dc:creator>
				<category><![CDATA[Lua]]></category>
		<category><![CDATA[coroutine]]></category>
		<category><![CDATA[Java]]></category>

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

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

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

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

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

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

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

<li><a href="http://timyang.net/programming/lighttpd-mod_cache-twitter/" rel="bookmark" title="July 5, 2009">关于阙宏宇lighttpd与mod_cache在twitter上的一些讨论</a></li>
</ul><!-- Similar Posts took 11.749 ms -->]]></content:encoded>
			<wfw:commentRss>http://timyang.net/lua/lua-coroutine-vs-java-wait-notify/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Lua coroutine 不一样的多线程编程思路</title>
		<link>http://timyang.net/lua/lua-coroutine/</link>
		<comments>http://timyang.net/lua/lua-coroutine/#comments</comments>
		<pubDate>Sun, 26 Apr 2009 15:23:27 +0000</pubDate>
		<dc:creator>Tim</dc:creator>
				<category><![CDATA[Lua]]></category>
		<category><![CDATA[coroutine]]></category>

		<guid isPermaLink="false">http://timyang.net/?p=102</guid>
		<description><![CDATA[上周末开始看《Lua程序设计》第二版，目前体会到其中比较有趣的有两点，一是强大的table数据结构，另外就是coroutine。也许Lua中的coroutine是一种很好的设计模式，但我初步的体会还是没想到其他语言和场合能非常适合用到coroutine的场景。
一、简介
协同程序与线程差不多，也就是一条执行序列，拥有自己独立的栈，局部变量和指令指针，同时又与其它协同程序共享全局变量和其它大部分东西。线程与协同程序的主要区别在于，一个具有多线程的程序可以同时运行几个线程，而协同程序却需要彼此协作地运行。就是说，一个具有多个协同程序的程序在任何时刻只能运行一个协同程序，并且正在运行的协同程序只会在其显示地挂起时，它的执行才会暂停。
如：
co = coroutine.create(function ()
for i=1,10 do
print("co", i)
coroutine.yield()
end
end)
从主线程调用
coroutine.resume(co)
会依次打印1到10
二、原理探析

coroutine创建的所谓的“线程”都不是真正的操作系统的线程，实际上是通过保存stack状态来模拟的。
由于是假的线程，所以切换线程的开销极小，同时创建线程也是轻量级的，new_thread只是在内存新建了一个stack用于存放新coroutine的变量，也称作lua_State

LUA_API lua_State *lua_newthread (lua_State *L)

调用yield()当前线程交出控制权，同时还可以通过stack返回参数。调用resume的线程(可理解为主线程)获得返回的参数。
Lua yield()和Java中的Thread.yield()有点相似，但是区别更大。Java中的yield调用后只是将当前CPU切换到另外一个线程，CPU可能随时会继续回到线程执行。
我更倾向于把Lua中的yield()和resume()和Java中的wait()和notify()来对比。它们表现的行为基本一致。
关于stack实现也可参看Yufeng(Erlang高手)的分析文章 lua coroutine是如何实现的？

三、Why coroutine?
上面对coroutine有个基本的了解，因此大家都会象我一样去想，为什么要用coroutine？先研究下优点

每个coroutine有自己私有的stack及局部变量。
同一时间只有一个coroutine在执行，无需对全局变量加锁。
顺序可控，完全由程序控制执行的顺序。而通常的多线程一旦启动，它的运行时序是没法预测的，因此通常会给测试所有的情况带来困难。所以能用coroutine解决的场合应当优先使用coroutine。

再看缺点，研究coroutine缺点之前，我寻找了一下Lua中为什么实现coroutine的一些说明。在巴西人写的paper Coroutines in Lua(pdf)中解释了几个原因：

Lua是ANSI C实现的，ANSI C并不包含thread的实现，因此如果要在Lua增加thread的支持就要使用操作系统本地的实现，这样会造成通用的问题。同时也会使Lua变得臃肿。因此Lua选择了在ANSI C上实现的coroutine。
Lua主要设计目的之一是给C调用，如果Lua内部又有多线程实现的话会造成C调用状态的混乱，而只提供coroutine层面的挂起则可以保持状态的一致性。

以上这些理由都是基于Lua特殊的原因而使用的，并不是很通用的原因。我们也了解到，coroutine实际上是一种古老的设计模式，它在60年代就已经定型，但是现代语言很少有重视这个特性，目前可以举例的有Windows的fibers, Python的generators
四、Lua coroutine和Erlang
上面优点有1条没展开，就是每个coroutine有自己私有的stack及内存变量空间。因此可以认为coroutine和Erlang中的process是非常相似的。但是coroutine只能同时只有一个在执行，如果能让他多个同时跑，我觉得就和Erlang非常相似了。
《Lua程序设计》第二版30.2介绍的一种实现方法，让多个c threads启动，然后每个c thread启动一个coroutine(类似Erlang process)，然后通过stack传递变量值(类似Erlang process message)，这样就可以实现一个类似Erlang的process模型了。由于coroutine实际上可以用任何语言实现，那其他语言应该也可实现同样这种设计方法。
五、Lua其他
Lua目前主要用在游戏编程领域，通常的观点Lua是“胶水语言”。用来把各个模块化的功能粘合起来。就我目前阅读的一些代码来看，C和Lua通常是混合在一起的，并没有明确的边界。对于我一个外行的眼光看来我分不清哪些是在做C的事情，哪些是在调用Lua。特别是这个“胶水”如果放得太多，系统中各个模块的独立性将会受到影响。比如云风的这篇Lua 不是 C++也提到，“这属于过厚的粘合层，是绝对需要抛弃的”。
另外Code@Pig一篇[网游设计] 一点感想也提到要简化调用，我总结它的观点主要两点：

不要存在冗余的关系，给一个部分负责管理就好。(由Lua/python来管理)
粘合层(Lua/python接口)不要过胖，我们可以通过引入一个“间接层”来把粘合层做“薄”

虽然Lua的高效和精简的设计让人赞誉有加，但是它的性能排名并不高，和Python大致在同一个级别。另外“胶水语言”的定位也妨碍了它在更多领域的发展。
Similar Posts:Lua coroutine vs Java wait/notify

使用脚本引擎增加程序运行时动态执行能力(Java篇)

参加Erlang开发者大会一些记录

2010年的技术架构建议

python web.py使用flup lighttpd优化过程
]]></description>
			<content:encoded><![CDATA[<p>上周末开始看《Lua程序设计》第二版，目前体会到其中比较有趣的有两点，一是强大的table数据结构，另外就是coroutine。也许Lua中的coroutine是一种很好的设计模式，但我初步的体会还是没想到其他语言和场合能非常适合用到coroutine的场景。</p>
<h1>一、简介</h1>
<blockquote><p>协同程序与线程差不多，也就是一条执行序列，拥有自己独立的栈，局部变量和指令指针，同时又与其它协同程序共享全局变量和其它大部分东西。线程与协同程序的主要区别在于，一个具有多线程的程序可以同时运行几个线程，而协同程序却需要彼此协作地运行。就是说，一个具有多个协同程序的程序在任何时刻只能运行一个协同程序，并且正在运行的协同程序只会在其显示地挂起时，它的执行才会暂停。</p></blockquote>
<p>如：</p>
<pre>co = coroutine.create(function ()
for i=1,10 do
print("co", i)
coroutine.yield()
end
end)</pre>
<p>从主线程调用<br />
coroutine.resume(co)<br />
会依次打印1到10</p>
<h1>二、原理探析</h1>
<ul>
<li>coroutine创建的所谓的“线程”都不是真正的操作系统的线程，实际上是通过保存stack状态来模拟的。<a href="http://mryufeng.javaeye.com/blog/211004" target="_blank"></a></li>
<li>由于是假的线程，所以切换线程的开销极小，同时创建线程也是轻量级的，new_thread只是在内存新建了一个stack用于存放新coroutine的变量，也称作lua_State</li>
</ul>
<p>LUA_API lua_State *lua_newthread (lua_State *L)</p>
<ul>
<li>调用yield()当前线程交出控制权，同时还可以通过stack返回参数。调用resume的线程(可理解为主线程)获得返回的参数。</li>
<li>Lua yield()和Java中的Thread.yield()有点相似，但是区别更大。Java中的yield调用后只是将当前CPU切换到另外一个线程，CPU可能随时会继续回到线程执行。</li>
<li>我更倾向于把Lua中的yield()和resume()和Java中的wait()和notify()来对比。它们表现的行为基本一致。</li>
<li>关于stack实现也可参看Yufeng(Erlang高手)的分析文章 <a href="http://mryufeng.javaeye.com/blog/211004" target="_blank">lua coroutine是如何实现的？</a></li>
</ul>
<h1>三、Why coroutine?</h1>
<p>上面对coroutine有个基本的了解，因此大家都会象我一样去想，为什么要用coroutine？先研究下优点</p>
<ul>
<li>每个coroutine有自己私有的stack及局部变量。</li>
<li>同一时间只有一个coroutine在执行，无需对全局变量加锁。</li>
<li>顺序可控，完全由程序控制执行的顺序。而通常的多线程一旦启动，它的运行时序是没法预测的，因此通常会给测试所有的情况带来困难。所以能用coroutine解决的场合应当优先使用coroutine。</li>
</ul>
<p>再看缺点，研究coroutine缺点之前，我寻找了一下Lua中为什么实现coroutine的一些说明。在巴西人写的paper<a href="http://www.inf.puc-rio.br/~roberto/docs/corosblp.pdf" target="_blank"> Coroutines in Lua</a>(pdf)中解释了几个原因：</p>
<ul>
<li>Lua是ANSI C实现的，ANSI C并不包含thread的实现，因此如果要在Lua增加thread的支持就要使用操作系统本地的实现，这样会造成通用的问题。同时也会使Lua变得臃肿。因此Lua选择了在ANSI C上实现的coroutine。</li>
<li>Lua主要设计目的之一是给C调用，如果Lua内部又有多线程实现的话会造成C调用状态的混乱，而只提供coroutine层面的挂起则可以保持状态的一致性。</li>
</ul>
<p>以上这些理由都是基于Lua特殊的原因而使用的，并不是很通用的原因。我们也了解到，coroutine实际上是一种古老的设计模式，它在60年代就已经定型，但是现代语言很少有重视这个特性，目前可以举例的有Windows的fibers, Python的generators</p>
<h1>四、Lua coroutine和Erlang</h1>
<p>上面优点有1条没展开，就是每个coroutine有自己私有的stack及内存变量空间。因此可以认为coroutine和Erlang中的process是非常相似的。但是coroutine只能同时只有一个在执行，如果能让他多个同时跑，我觉得就和Erlang非常相似了。</p>
<p>《Lua程序设计》第二版30.2介绍的一种实现方法，让多个c threads启动，然后每个c thread启动一个coroutine(类似Erlang process)，然后通过stack传递变量值(类似Erlang process message)，这样就可以实现一个类似Erlang的process模型了。由于coroutine实际上可以用任何语言实现，那其他语言应该也可实现同样这种设计方法。</p>
<h1>五、Lua其他</h1>
<p>Lua目前主要用在游戏编程领域，通常的观点Lua是“胶水语言”。用来把各个模块化的功能粘合起来。就我目前阅读的一些代码来看，C和Lua通常是混合在一起的，并没有明确的边界。对于我一个外行的眼光看来我分不清哪些是在做C的事情，哪些是在调用Lua。特别是这个“胶水”如果放得太多，系统中各个模块的独立性将会受到影响。比如云风的这篇<a href="http://blog.codingnow.com/2008/08/lua_is_not_c_plus_plus.html" target="_blank">Lua 不是 C++</a>也提到，“这属于过厚的粘合层，是绝对需要抛弃的”。</p>
<p>另外Code@Pig一篇<a href="http://kasicass.blog.163.com/blog/static/3956192009321112711785/" target="_blank">[网游设计] 一点感想</a>也提到要简化调用，我总结它的观点主要两点：</p>
<ol>
<li>不要存在冗余的关系，给一个部分负责管理就好。(由Lua/python来管理)</li>
<li>粘合层(Lua/python接口)不要过胖，我们可以通过引入一个“间接层”来把粘合层做“薄”</li>
</ol>
<p>虽然Lua的高效和精简的设计让人赞誉有加，但是它的<a href="http://shootout.alioth.debian.org/gp4/benchmark.php?test=all&amp;amp;amp;lang=all" target="_blank">性能排名</a>并不高，和Python大致在同一个级别。另外“胶水语言”的定位也妨碍了它在更多领域的发展。</p>
Similar Posts:<ul><li><a href="http://timyang.net/lua/lua-coroutine-vs-java-wait-notify/" rel="bookmark" title="April 27, 2009">Lua coroutine vs Java wait/notify</a></li>

<li><a href="http://timyang.net/java/java-scripting/" rel="bookmark" title="May 18, 2009">使用脚本引擎增加程序运行时动态执行能力(Java篇)</a></li>

<li><a href="http://timyang.net/erlang/cn-erlounge-iii/" rel="bookmark" title="December 26, 2008">参加Erlang开发者大会一些记录</a></li>

<li><a href="http://timyang.net/architecture/2010-tech-predictions/" rel="bookmark" title="December 31, 2009">2010年的技术架构建议</a></li>

<li><a href="http://timyang.net/python/python-webpy-lighttpd/" rel="bookmark" title="February 26, 2009">python web.py使用flup lighttpd优化过程</a></li>
</ul><!-- Similar Posts took 11.664 ms -->]]></content:encoded>
			<wfw:commentRss>http://timyang.net/lua/lua-coroutine/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>
