最近在测试简单的轻量级线程调度器。从fiber转换到generator,性能是提升了不少,但却在意想不到的地方出现了瓶颈。
在generator本身切换性能测试时,发现它性能非常高,大概单线程里面每秒切换有2亿次以上,比fiber的200-400万次有了质的提高。但是在实现了一个简单的调度器以后,发现性能急骤下降,到了每秒千万次,实现方式是使用标准库提供的list容器。
在测试了c++标准库的std::list和c#的几个list容器以后,发现它们性能都非常低,每秒仅能处理上千万次尾部添加和头部删除操作。简单分析后可以确认,性能降低是由于频繁的分配释放引起的,改用g++的ext/poll_ ...
前面说地Generator编写并发程序的优势,当然它本身没有这种能力,需要为它编写调度程序。
今天抽点时间写了个简单的,还是满好玩的,它可以调度多个“友好”的并发任务,包括:
1、用户自己编写的适时交出控制权的过程
2、网络IO
由于对C#不是很熟,所以写的可能比较难看,而且IO也只支持网络,有兴趣的可以研究改进一下,比如把它改成SMP版本,增加Actor模型,处理更多的IO模式等。
实现方式基本上是从IoLanguage里面抄过来的,我已经用它编写过Ruby/C++/D/C#版本,当然目前仅限于测试它的切换性能。
好消息是如果你实现得比较好,C#版本性能完全可以超过Erlang,Ru ...
一直没搞清云计算和网格计算的差别,为什么就提出个新词了呢?
通过对Amazon的Google的观察,发现这两家公司产品方向的一些共同点。
1、软件即服务
Google App Engine和Amazon SimpleDB/S3都是提供服务的,类似的例子还有最近比较火的各种开放接口。
2、应用容器,自动部署,超强的扩展能力
Google App Engine更能体现这点。由于开放的所有接口都是调用服务,应用运行的容器本身完全不需要保存任何状态,它只需要有强劲的CPU、内存和网络设备,任何时候都可以把服务横向扩展到多台服务器上。
3、后台技术
分布式文件系统,分布式DB,都需要提供超强的性 ...
几种并发编程模型开销(从大到小):
Process > Thread > Coroutine > Generator == Callback
从对机器的并行利用来说,却是完全相反的。
Process可以部署在不同机器上;
Thread需要在Process里面,往往是很多Thread在一个Process里面,它对多CPU利用还是比较充分的;
Coroutine在Thread里面运行,要利用多CPU,需要实现调度器;
Generator算是一种带有状态的Callback,或者是对象化的Callback,它们也需要运行在Thread里面,要利用多CPU,需要实现调度器;
为什么Generat ...
先总结一下。
线程是最容易编写的并发方式,操作系统也提供了最好的支持;协程可以做到更强的并发能力,但需要实现调度器;回调是开销最小的,它本来不是特别为并发来设计的,它是通用的异步化操作的实现模型。
注意线程和协程本身也是使用异步来模拟同步,线程由操作系统来模拟,协程由用户级调度器模拟。模拟的过程是:发起事件请求、挂起当前执行过程(线程或协程)、响应事件请求、恢复挂起的执行过程。回调没有这么复杂,你需要自己把连续的执行过程分解成多步操作。
线程就不讨论了,用起来比较简单;协程之前简单研究了一下,切换开销比线程有很大改进,但还是有点大,用作IO事件调度还可以,粒度更小的操作就显得开销过大了, ...
Coroutine切换成本相对还是比较高的,把一个并发程序改成Coroutine实现性能上可能有比较大的损失。Coroutine切换主要是大量寄存器压栈和弹栈,栈切换也会影响到cache。目前C/C++大量使用的是回调方式,比如win32窗口编程、libevent等,优点是高效,函数调用成本是很低的,也没有栈切换,缺点是不如Coroutine这样连贯。有没有方法让它具有两者的优点呢?有Coroutine连贯的过程,也有Callback的高效?还是考虑这个简单的例子:
(本文代码使用D语法,但并没有编译测试)
void client_loop(int fd) {
while(tru ...
前段时间公司网站出过两次事故,前台跑PHP的Apache进程大量死锁,造成服务器无负载但不能提供服务,不断重启服务也未能解决问题,但过几小时后自动恢复。这些系统已经稳定运行数月之久,虽然不断有升级但没有出现这类情况。
一周后第二次出现相同情况时公司组织人力进行了排查,没有发现问题。由于没有WEB机器登录权限,于是让运维同事做了这些操作来查找原因:
1、strace -p xxxx查看任意httpd进程,查看进程运行状态。如果没有阻塞在futex上,换一个进程再查看。
这一步一般可以查出很多原因,比如死循环,如果strace没有显示一个系统调用正在进行,一般是限入无终结条件的死循环,这种情况 ...
简单比较了一下ucontext和Erlang的进程切换效率,在我的机器上ucontext每秒可以完成90万次切换,Erlang则要快得多,每秒可以完成412万次切换,这个性能比较和之前shootout上的测试相近。
效率差这么多是可以预见的,C的轻量级线程实现都是栈切换的,要完成寄存器保存和加载,只是不需要经过系统调度。相比之下其它语言的轻量级线程切换通常不是C栈切换,开销要小得多。
有这么大的差距是不是Erlang就有很大的性能优势呢?我觉得不是。Erlang为了保证实时性,把进程调度的粒度设置到函数调用这个级别上,复杂的应用中很容易导致过多的切换;而C实现则是由程序员自己找准时机来切换 ...
理论知识太少,表达能力太差,简单发点自己的总结,有意见请不要给我面子
下面所列的几个场景只是我接触过的几个,并不是最适合用来说明Coroutine应用的,如果你有更好的例子或是反对意见,我希望听到不同的声音。我对Coroutine的理解只是皮毛,并没有大规模应用过,也想听到一些应用经验。
首先我得承认我对于并发、异步、并行、分布式这些概念毫无兴趣,我甚至讨厌理论相关的东西,我也不能给它们做出准确的解释,我只是不断寻找更简单的编码方式。
并发应用场景
场景一:基于状态机的并发协议处理
状态机通常用于把一段处理过程分解成有限个稳定的状态,在处理过程中在这些状态间切换。举一个简单的协议例 ...
- 21:20
- 浏览 (767)
- 评论 (15)
最近下决心和Erlang说再见了,想了很多,也用了一段时间,断断续续数落过几次Erlang的优缺点,看得不深,权当我是瞎说。简单整理一下:
优点:高并发、分布式、资源管理、高效率(和其它动态语言比较)、热升级、自动并行
缺点:语言抽象能力不强、语言扩展能力不强、FP让大多数人不适应、和C库交互不好
有一段时间我打算自己做一套类似的框架,使用coroutine,虽然我测试过的coroutine库都不如Erlang高效(注1),但C编写处理代码比Erlang高效多了,完全可以弥补。和C库的交互可以更自然地实现。我不打算做个多线程的调度器,因为有太多第三方库需要线程池、异步IO去完成的操作,这些 ...
- 21:42
- 浏览 (579)
- 评论 (6)
- 分类: IoLanguage
- 浏览: 167579 次
- 性别:

- 来自: 上海

- 详细资料
搜索本博客
链接
最新评论
-
标准库的效率--适时选择自 ...
哦。我的意思是说使用池也只是少量提升性能而已,对于有些应用来说绝对不要使用这些库 ...
-- by qiezi -
标准库的效率--适时选择自 ...
使用对象池可以吗, 老的对象不销毁
-- by inshua -
标准库的效率--适时选择自 ...
如果对象的生命周期适合"allocate many objects and th ...
-- by yawl -
云计算的架构
还是没搞清云计算和网格计算的差别啊
-- by enjoyeveryday -
云计算的架构
感觉云计算本质上就是网格的再次商业包装,大公司老这样干的。请参考Wikipedi ...
-- by turing






评论排行榜