转载:http://shiningray.cn/some-facts-about-erlang-and-smp.html
原文:http://groups.google.com/group/erlang-questions/browse_thread/thread/7827f5e32681ca8e
by.Kenneth Erlang/OTP team, Ericsson
译:ShiningRay
以下是一些Erlang SMP实现的细节和与性能与伸缩性相关一些简单介绍。
几周之内还有有一个关于多核如何运作以及未来如何发展的更详细的介绍。我打算将一些内容放在我的报告中,将于9月27日的ICFP2008,Erlang Workshop在Victoria BC展示给大家。
没有SMP支持的Erlang VM只有1个运行在主处理线程中的调度器。该调度器从运行队列(run-queue)中取出可以运行的Erlang进程以及IO任务,而且因为只有一个线程访问他们所以无须锁定任何数据。
而带有SMP支持的Erlang VM可以有一个或多个调度器,每个运行在一个线程中。调度器从同一个公共运行队列中取出可运行的Erlang进程和IO任务。在SMP VM中所有的共享数据结构都会由锁进行保护,运行队列就是这样一个由锁保护的数据结构。
从OTP R12B开始,如果操作系统报告有多于1个的CPU(或者核心)VM的SMP版本会自动启动,并且根据CPU或者核心的数量启动同样数量的调度器。
你可以从“erl”命令打印出来的第一行看到它选择了哪些参数。例如:
Erlang (BEAM) emulator version 5.6.4 [source] [smp:4] [asynch-threads:0] …..
其中“[smp:4]”表示SMP VM运行了4个调度器。
默认值可以用“-smp [enable|disable|auto]”来替换,auto是默认的。如果smp被启用了(-smp enable),要设置调度器的数量可以使用“+S Number”其中Number是调度器的数量(1到1024)
注意1:运行多于CPU或核心总数的调度器不会有任何提升。
注意2:在某些操作系统中一个进程可使用的CPU或者核心的数量可以被限制。例如,在Linux中,命令“taskset”就可以实现这个功能。Erlang VM目前还只能探测CPU或者核心的总数,不会考虑“taskset”所设置的掩码。正因如此,例如可能会出现(已经出现过了)即使Erlang VM运行了4个调度器,也只使用了2个核心。OS会进行限制因为它要考虑“taskset”所设置的掩码。
每个Erlang VM的调度器都运行于一个OS线程上,是OS来决定线程是否执行在不同的核心上。一般来说OS会很好地处理这个问题并且会保证线程在执行期间运行于同一个核心上。
Erlang进程会被不同的调度器运行,因为他们是从一个公共运行队列中被取出,由首先可用的调度器运行。
性能和伸缩性
只有一个调度器的SMP VM要比非SMP的VM稍微慢那么一点点。SMP VM内部需要用到各种锁,不过只要不存在锁的争用,那么由锁引起的开销不会非常大(就是锁争用上面需要花时间)。这也解释了为何在某些情况下,运行多个只有一个调度器的SMP VM要比包含多个调度器的单一SMP VM更加高效。当然运行多个VM要求应用可以按照多个并行任务的方式运行并且之间没有或者几乎不通讯。
一个程序是否能在多核上的SMP VM中良好地进行提升很大程度上取决于程序的性质,某些程序可以保持线性提升至8核甚至16核,同时其他某些程序基本不能提升,连2核都不行。实际应用中很多程序都能在主流市场的核心数上得到提升,见下文。
若并行的持续“通话”由每个核心一个或多个Erlang进程来表示,实际的支持大量通话的电信产品已经先现出在双核和四核处理器上不俗的伸缩性。注意,这些产品是在SMP VM和多核处理器出现很久以前按照普通的Erlang风格来写的,他们也能无须任何修改甚至不需重新编译代码就能从Erlang SMP VM中获益。
SMP性能得到持续改进
SMP实现正被不断改进以便能得到更好的性能和伸缩性。在每个服务发布版R12B-1,2,3,4,5…,R13B等等中,你都能发现新的优化。
一些已知的瓶颈
单一的常见运行队列随着CPU或核心的数量的增加会成为一个显著的瓶颈。
这从4核开始往上就会显现出来,不过4核仍然可以为多数应用程序提供不错的性能。我们正在从事一个每个调度器一个运行队列的解决方法作为目前最重要的改进。
Ets表格会引入锁。在R12B-4之前在每次对一个ets-table的访问中会用到两个锁,但是在R12B-4中meta-table的锁被优化过,可以显著减少争用(前面已经提到争用是有很大代价的)。如果很多Erlang进程访问同一个表格,就会有很多锁争用造成性能降低尤其当这些进程主要工作是访问ets-table。锁存在于表级而非记录级。注意!这也会影响到Mnesia因为Mnesia用到了很多ets-table。
我们关于SMP的策略
当我们开始实现SMP VM的最初,我们就确定了策略:“首先让它可以运行,然后测量,然后优化”。自从2006年五月我们发布了第一个稳定的SMP VM(R11B)以来,我们一直遵循着这个策略。
还有更多已知的东西可以改进,我们会按照性能的收益大小先后各个击破。
我们将主要的精力放在多核(大于4)上更好的连续伸缩性上。
卓越典范
即使SMP系统有还有一些已知的瓶颈不过已经有不错的整体性能和伸缩性,同时我相信在让程序员利用多核机器事半功倍方面,我们是一个卓越的典范。