把 lua 和 event loop 结合起来,是不是比 js 更给力 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
这是一个专门讨论 idea 的地方。

每个人的时间,资源是有限的,有的时候你或许能够想到很多 idea,但是由于现实的限制,却并不是所有的 idea 都能够成为现实。

那这个时候,不妨可以把那些 idea 分享出来,启发别人。
ryanking8215
V2EX    奇思妙想

把 lua 和 event loop 结合起来,是不是比 js 更给力

  •  
  •   ryanking8215 2014-03-11 14:33:13 +08:00 8975 次点击
    这是一个创建于 4309 天前的主题,其中的信息可能已经有所发展或是发生改变。
    js把event loop融入了它的血液了。从语法上看,lua和js相像的地方很多,大不同的地方是,lua都是同步接口,但所幸lua的core很小,是不是把它改动一下,结合libuv,也做成一个lua-async的东东,在通过luajit,是不是比js更给力?

    当然,前后端大一统就没了。lua和c/c++结合比用v8简单太多了。

    欢迎大家吐槽!
    28 条回复    1970-01-01 08:00:00 +08:00
    darklowly
        1
    darklowly  
       2014-03-11 14:46:18 +08:00 via iPhone
    为什么不直接用go
    seeker
        2
    seeker  
       2014-03-11 14:48:37 +08:00
    刚搜了下搜到这个,给撸主参考参考: http://luvit.io/
    mingzhi
        3
    mingzhi  
       2014-03-11 14:50:44 +08:00
    lz 说的是这货 http://luvit.io/ 这样?
    ryanking8215
        4
    ryanking8215  
    OP
       2014-03-11 14:51:43 +08:00
    golang也是同步的啊

    我靠,真有这玩意儿,还说比node.js快2~4倍。
    initialdp
        5
    initialdp  
       2014-03-11 15:19:40 +08:00
    国内云风开源的skynet据说也是杠杠的。
    clino
        6
    clino  
       2014-03-11 15:35:06 +08:00   1
    用lua当然要用coroutine了,为什么还用event loop这种编程界面这么恶心的东东呢
    ryanking8215
        7
    ryanking8215  
    OP
       2014-03-11 15:54:52 +08:00
    我不觉得event loop很恶心啊,嵌入式上一直用libevent。
    最近觉得多线程会造成心智负担,担心死锁的问题。包括goroutine。
    callback嵌套多点就多点吧,不是还有async,eventproxy么?至少我知道cpu在执行这里的时候,别的代码对这个没影响。难道是年纪大了?
    alsotang
        8
    alsotang  
       2014-03-11 16:02:02 +08:00
    反正 nodejs 的嵌套很恶心就对了。
    kran
        9
    kran  
       2014-03-11 16:03:19 +08:00
    openresty, alilua ?
    clino
        10
    clino  
       2014-03-11 17:02:37 +08:00
    @ryanking8215 如果用同步的方式写会有死锁,那么用eventloop方式一样会有吧
    superhack
        11
    superhack  
       2014-03-11 20:09:52 +08:00
    openresty 中的 ngx_lua
    ryanking8215
        12
    ryanking8215  
    OP
       2014-03-11 20:54:42 +08:00
    @clino 用了单进程单线程的eventloop,那就不用锁了,就不会有死锁了。死锁不是因为同步写的原因,是因为要并发,临界区资源需要互斥,有资源需要同步访问,也有可能多个任务需要协调同步等等,就有锁的问题,一不小心就会死锁,其实死锁还好,万一临界区资源被无故改写,这个问题很难查,很难重现。
    suninus
        13
    suninus  
       2014-03-11 20:55:52 +08:00 via Android
    这个点个赞,@seeker真搜度
    clino
        14
    clino  
       2014-03-11 21:28:35 +08:00
    @ryanking8215 coroutine 一样可以是单进程单线程来并发,照你这么说也不用锁
    RIcter
        15
    RIcter  
       2014-03-11 21:33:33 +08:00
    @seeker 好眼熟,我们是不是在哪见过,bathome么。。不对。。
    ryanking8215
        16
    ryanking8215  
    OP
       2014-03-12 09:15:40 +08:00
    @clino 你指lua的coroutine吗?lua不是很熟悉,但我记得是没有锁啊
    clino
        17
    clino  
       2014-03-12 10:04:18 +08:00
    @ryanking8215 coroutine在几种语言的实现都是单线程里并发的,照你说都不用有锁了
    另外event loop就不用锁了吗?你确定吗?
    ryanking8215
        18
    ryanking8215  
    OP
       2014-03-12 10:20:31 +08:00
    @clino 单线程单进程的event loop不需要锁,我确定。你说几种语言的coroutine的,我不是了解很多语言,单从lua讲,是单线程内执行的协程,不需要锁。 至于goroutine,是多线程支撑的CSP模型,需要锁的,它也提供的sync.Mutex,sync.Atomic,当然它提供更方便的chan是另一说了
    clino
        19
    clino  
       2014-03-12 10:46:14 +08:00
    @ryanking8215 gevent是单线程的,它一样提供锁的工具( http://xlambda.com/gevent-tutorial/#_11 ),可以用来"限制并发访问或运行",当然也可以不用
    不过 event loop 确实就没办法用了,所以在这点上也能看出这种编程接口没coroutine灵活
    至于goroutine,你要想做成单线程一样也可以,这是使用者的选择,不一定非要用多线程的方式
    ryanking8215
        20
    ryanking8215  
    OP
       2014-03-12 11:39:13 +08:00
    @clino 我看了一下gevent,我同意你的说法。我的理解是从资源保护上讲,是不需要锁的,因为gevent的cpu是用户显示释放的,不是OS调度的,没有临界区的问题,但是你要同步gevent,控制gevent的执行顺序,就需要信号量和锁了。

    但是你说的关于goroutine的,我不太认同,goroutine是go runtime的调度器调度的,什么时候切换goroutine是自动的,不是用户控制的,如果没有互斥和同步原语,我觉得是有临界区问题的。我不清楚如何起n个gorouine是保证在一个线程上的。
    clino
        21
    clino  
       2014-03-12 12:48:21 +08:00
    @ryanking8215 你保证是在一个线程里使用 goroutine 不就可以保证这个线程里的goroutine不会并行执行了嘛
    用不用多线程或者多进程难道你不能决定吗?
    ryanking8215
        22
    ryanking8215  
    OP
       2014-03-12 13:17:41 +08:00
    @clino goroutine和lua的coroutine还有gevent等这种协程是不同的概念。
    协程生成在哪个线程上,就在哪个线程进行上下文切换,

    但在golang里没有线程的概念,goroutine的这种设计屏蔽了操作系统的线程,目前的并发是使用线程来实现的,m个goroutine跑在n个线程上(m>=n),当你起goroutine时,golang的调度器负责将goroutie分配给已有线程或者新建线程。

    你可以安装golang跑个例子看看
    clino
        23
    clino  
       2014-03-12 13:41:39 +08:00
    @ryanking8215 我对go确实不了解,但刚才搜了一下应该也是可以配置的,而且应该是默认为单线程
    http://blog.chinaunix.net/uid-22312037-id-3760407.html
    " 默认情况下,调度器仅适用单线程,也就是说只实现了并发。想要发挥多核处理器的并行,需要在程序中显示调用runtime.GOMAXPROCS(n)告诉调度器同时使用多个线程。GOMAXPROCS设置了同时运行逻辑代码的系统线程的最大数量,并返回之前的设置。如果n<1,不会改变当前设置。关于并发和并行请参看rob的这篇文章"
    ryanking8215
        24
    ryanking8215  
    OP
       2014-03-12 14:02:01 +08:00
    @clino http://golang.org/pkg/runtime/#GOMAXPROCS, 是设置多少个cpu参与并行,而不是线程数。

    这篇东西完全在误导!

    我刚才试了了一下:
    func main() {
    <- time.After(5*time.Minute)
    }
    简单的定时器,golang帮我开了5个线程,包括主线程,通过ls /proc/<pid>/task/查看
    clino
        25
    clino  
       2014-03-12 14:52:54 +08:00
    @ryanking8215 看起来我给的这篇是不靠谱,goroutine确实和coroutine差别比较大,我之前想当然了
    我想弄个go来试试,不过到现在没下载完

    又搜到一篇: http://xiezhenye.com/2012/08/%e5%86%8d%e6%8e%a2-goroutine.html

    "goroutine 并不是像我之前认为的,在 cgocall 或者 syscall 的时候进行自动切换,而是使用了线程。同时,这个线程数和 runtime.GOMAXPROCS 也没有直接关联。在这个情况下,虽然 runtime.GOMAXPROCS 设为了 2 ,但是最后照样用了 1000 多个线程。但是 strace -f ./par 直接运行,此时跟踪线程数,最多就只有几十个。看来和 less 也有关系"

    "go 语言要避免大量线程产生的切换开销,用类似 coroutine 的方式,还是得结合异步 io 。但是目前只在网络 io 上实现了这点。对于其他的 io,比如文件系统,仍然会由于阻塞而产生线程。如果应用中需要使用文件 io,就得使用生产者消费者模式来减少线程数量,或者可以考虑利用 netfd 的代码来实现一个其他类型 io 的异步包装(当然功能上会有一些限制)"
    ryanking8215
        26
    ryanking8215  
    OP
       2014-03-12 15:18:36 +08:00
    @clino 他说的是对的,第一段的“同时,这个线程数和 runtime.GOMAXPROCS 也没有直接关联。在这个情况下,虽然 runtime.GOMAXPROCS 设为了 2 ,但是最后照样用了 1000 多个线程。”,这句话没错,但是本来这2个就没有关系,并发和并行是2个概念,一个cpu可以通过开启n多个线程/进程并发或使用多个协程并发或使用event_loop并发,但不是并行计算,因为只有一个cpu,多个cpu参与就可以并行计算,多线程/多进程模型可以支持并行,但协程和event_loop就不支持了。

    第二段说的包装io,libuv就封装了异步的io,是通过线程来实现的,毕竟filesystem io是block的。

    goroutine把并发和并行结合了起来,而且不造成过多负担,模型一致。

    我这样理解的并发(cocurrency)和并行(parallel):并发是逻辑上的“并发”,并行是物理上的“并发”。
    clino
        27
    clino  
       2014-03-12 16:13:16 +08:00
    @ryanking8215 感觉很奇怪
    如下代码,如果是只有一个go func() ,我这里是4个线程,如果有3个 go func(),则变成3个线程
    不知道go内部是啥逻辑

    func main() {
    runtime.GOMAXPROCS(1)
    go func() {
    time.Sleep(3*time.Second)
    fmt.Println("Hello, World. after 3 seconds")
    }()
    go func() {
    time.Sleep(4*time.Second)
    fmt.Println("Hello, World. after 4 seconds")
    }()
    go func() {
    time.Sleep(5*time.Second)
    fmt.Println("Hello, World. after 5 seconds")
    }()

    time.Sleep(6*time.Second)
    fmt.Println("end")
    }
    ryanking8215
        28
    ryanking8215  
    OP
       2014-03-12 16:32:34 +08:00
    这个是golang的调度器实现的,具体的我也不懂了,没研究过。
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     2579 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 26ms UTC 06:29 PVG 14:29 LAX 22:29 JFK 01:29
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86