在windows下做了实验,用erlang shell起60万个erlang进程,占用内存760多M,平均每个进程占用内存1.27K,创建每个进程的时间约4微秒。在配置好得多的linux服务器上,用pthread起线程,平均每个线程创建时间48微秒。
查了一下资料(http://www.erlang.org/pipermail/erlang-questions/2006-October/023258.html,http://lambda-the-ultimate.org/node/1742#comment-21214,http://www.erlang.org/ml-archive/erlang-questions/200104/msg00072.html),了解了一下erlang进程的实现方式。总结一下erlang实现轻量级进程大概有以下几点:
1,erlang在用户态下实现的进程调度器。erlang虚拟机在进程处于等待期间,或进程运行1000个reductions时进行切换。一个reduction约等于一次函数调用。
2,面向语言的内存管理和进程切换机制提高了erlang的进程效率。也就是说,进程切换时,虚拟机知道一个进程哪些信息是需要保存的,哪些是没必要保存的(这个跟函数式语言应该很有关系,指针式语言中很难做到这一点)。而操作系统的线程切换时,栈、寄存器等所有上下文都需要保存下来。
3,pthread给每个线程预先分配固定大小的栈空间,不管实际上能用多少;而erlang进程最小只有大概32到64个字节的栈空间,当需要时可以增长。
4,只利用消息传递进行通信。对于在receive->处等待而导致切换的进程,没有状态需要保存。
5,这个是我猜想的。跟函数式语言的惰性求值也有关系。
比如
v->some_caculate(),
s1 -> somewhatLongOperation1(),
s2 -> somewhatLongOperation2(),
s3 -> concatenate(s1, s2).
如果进程在完成计算s2之后,计算s3之前发生切换。那么由于惰性求值,v的值尚未进行计算(由于暂时用不到),因此进程切换时就不需要保存v的信息。
总结一下,erlang进程的效率主要来自有用的信息都保存在栈上;虚拟机知道哪些信息是有用的并且只保存那些有用的信息。更深入的理解还是要看一下erlang的实现,以及对函数式语言的深入了解。