标签:val 面向 .net 协程库 sof 编写 一个人 cti 解决
先看的这篇文章:http://blog.csdn.net/qq910894904/article/details/41699541
以nginx为代表的事件驱动的异步server正在横扫天下,那么事件驱动模型会是server端模型的终点吗?
我们可以深入了解下,事件驱动编程的模型。
事件驱动编程的架构是预先设计一个事件循环,这个事件循环程序不断地检查目前要处理的信息,根据要处理的信息运行一个触发函数。其中这个外部信息可能来自一个目录夹中的文件,可能来自键盘或鼠标的动作,或者是一个时间事件。这个触发函数,可以是系统默认的也可以是用户注册的回调函数。
事件驱动程序设计着重于弹性以及异步化上面。许多GUI框架(如windows的MFC, Android的GUI框架),Zookeeper的Watcher等都使用了事件驱动机制。未来还会有其他的基于事件驱动的作品出现。
基于事件驱动的编程是单线程思维,其特点是异步+回调。
协程也是单线程,但是它能让原来要使用异步+回调方式写的非人类代码,可以用看似同步的方式写出来。它是实现推拉互动的所谓非抢占式协作的关键。
协程的好处:
缺点:
https://www.zhihu.com/question/32218874
协程方便是因为“用代码来表示状态,而不是维护一坨数据结构来表示状态”,则客观得多。
作者:Tim Shen 链接:https://www.zhihu.com/question/32218874/answer/56255707 来源:知乎 著作权归作者所有,转载请联系作者获得授权。 讲点历史吧。 早期的Unix时代崇尚同步编程,当时设计的时候也没多想,管他什么性能不性能,先做出来再说。所以最开始人是开多进程(process)再用管子(pipe)连接起来的;多直观啊,我把东西推进管子里,你走你那头接一下。 不知道哪天人注意到开个千儿八百个进程机器就卡死了,这怎么行,所以我们只搞一个进程,里面有一坨打开的网络连接和文件,用select这个系统调用对io事件同时进行监听,谁先来我就处理谁。然而发现性能也不好,没什么卵用。 人们在这两条路上都想办法提升性能。进程这边人们又搞了多线程,结果还是不够。多线程还是吃内核资源,抗不住。 Linux忍不住了,搞出个epoll(不过我不知道和bsd的kqueue哪个在前)系统调用,就是红黑树改良版的select。这下子人开心了,真他妈快啊,开千儿八百个连接小意思,同时进行事件监听,判断连接的的id和事件的类型,再打(dispatch)到不同的回调函数里。 不知是不是市场原因,正巧这时候互联网开始火了,性能越好赚钱越多嘛,所以肯定来这套高效的接口,管他好不好用呢,反正俺们吃苦耐劳,外加抖M,才不怕手动维护状态。你多线程开太多最后不也是要手动维护状态。 不熟悉操作系统的开发人员们只知道有什么用什么,也没去多想怎么优化多线程。现在多线程优化出来了,叫协程,调度器有的有(比如go的用户态调度器)有的没有(比如yield),取决于怎么用。其内存开销仍然比异步回调要大(一个协程一个栈,而异步回调的话一个event loop一共就一个栈),但是现在内存也是便宜了,不算是瓶颈。人最关注的是“千万不能堵着(block)”,要千方百计让CPU转起来,这样concurrency才能上去。而到处乱开协程(因为比线程便宜啊)就能达到这个效果,开十万个协程内存也没爆炸,跑上24个就能把CPU打满。所以异步回调的这个优势已经没了。
------另一个人的回答---------
有时候总觉得 gevent(python的一个库) 这类协程库是被 python 的 GIL 逼出来的,如果原生线程支持足够好,协程的必要性可能并不一定很大。
协程最早来自高性能计算领域的成功案例,协作式调度相比抢占式调度而言,可以在牺牲公平性时换取吞吐。
Node.js需要按顺序执行异步逻辑时一般采用后续传递风格,也就是将后续逻辑封装在回调函数中作为起始函数的参数,逐层嵌套。这种风格虽然可以提高CPU利用率,降低等待时间,但当后续逻辑步骤较多时会影响代码的可读性,结果代码的修改维护变得很困难。根据这种代码的样子,一般称其为"callback hell"或"pyramid of doom",本文称之为回调大坑,嵌套越多,大坑越深。
注:monkey patch可以看:http://www.tuicool.com/articles/2aIZZb
monkey patch指的是在运行时动态替换,一般是在startup的时候. (感觉大多数是Python程序的一种技巧) 用过gevent就会知道,会在最开头的地方gevent.monkey.patch_all();把标准库中的thread/socket等给替换掉.这样我们在后面使用socket的时候可以跟平常一样使用,无需修改任何代码,但是它变成非阻塞的了. 之前做的一个游戏服务器,很多地方用的import json,后来发现ujson比自带json快了N倍,于是问题来了,难道几十个文件要一个个把import json改成import ujson as json吗? 其实只需要在进程startup的地方monkey patch就行了.是影响整个进程空间的. 同一进程空间中一个module只会被运行一次. 下面是代码. main.py import json import ujson def monkey_patch_json(): json.__name__ = ‘ujson‘ json.dumps = ujson.dumps json.loads = ujson.loads monkey_patch_json() print ‘main.py‘,json.__name__ import sub sub.py import json print ‘sub.py‘,json.__name__ 运行main.py,可以看到都是输出‘ujson‘,说明后面import的json是被patch了的. 最后,注意不能单纯的json = ujson来替换.
$ ulimit -s
10240
也就是10M;修改的方法如下:
linux查看修改线程默认栈空间大小 ulimit -s 1、通过命令 ulimit -s 查看linux的默认栈空间大小,默认情况下 为10240 即10M 2、通过命令 ulimit -s 设置大小值 临时改变栈空间大小:ulimit -s 102400, 即修改为100M 3、可以在/etc/rc.local 内 加入 ulimit -s 102400 则可以开机就设置栈空间大小 4、在/etc/security/limits.conf 中也可以改变栈空间大小: #<domain> <type> <item> <value> * soft stack 102400 重新登录,执行ulimit -s 即可看到改为102400 即100M
标签:val 面向 .net 协程库 sof 编写 一个人 cti 解决
原文地址:http://www.cnblogs.com/charlesblc/p/6186248.html