Erlang 17.5引入+hpds命令行控制进程默认字典大小

April 1st, 2015 4 comments

原创文章,转载请注明: 转载自系统技术非业余研究

本文链接地址: Erlang 17.5引入+hpds命令行控制进程默认字典大小

Erlang 17.5发布引入控制进程默认字典大小的命令行参数:

Erlang/OTP 17.5 has been released
Written by Henrik, 01 Apr 2015

Some highlights of the release are:
ERTS: Added command line argument option for setting the initial size of process dictionaries.

源码变化参看: https://github.com/erlang/otp/commit/c7a07bf984739bcc679d800e5383c01e1d07ffa5
文档:https://github.com/erlang/otp/commit/89987ada3c997fd9f1e1f8c8ed73da0394bda4ee

这个+hpds参数默认是字典有10个槽位,由于典型的Erlang VM内有成千上万的进程,官方又不鼓励使用字典,因为破坏fp语义,所以这些默认的字典占用的内存是浪费掉了。 挑小了对于内存敏感的嵌入式机器还是挺可观的;调大了对字典性能有一定的提升。

祝玩得开心!

Post Footer automatically generated by wp-posturl plugin for wordpress.

Categories: Erlang探索, 源码分析 Tags:

集群引入inet_dist_{listen,connect}_options更精细参数微调

April 1st, 2015 1 comment

原创文章,转载请注明: 转载自系统技术非业余研究

本文链接地址: 集群引入inet_dist_{listen,connect}_options更精细参数微调

Erlang 17.5版本引入了inet_dist_{listen,connect}_options,对于结点间的互联socket可以有更精细的控制,RPC的时候性能可以微调:

raimo/inet_tcp_dist-priority-option/OTP-12476:
Document kernel inet_dist_{listen,connect}_options
Test kernel inet_dist_{listen,connect}_options
Implement kernel inet_dist_{listen,connect}_options

参看源码:https://github.com/erlang/otp/commit/14ddc5594d74979a15a256a41fba5f1297aeaa1a

随着Erlang集群和节点上千,节点之间的RPC的开销和延迟就会被放大. 因为每个节点间的互通都是通过tcp, 驱动上也都是gen_tcp所以理论上对于gen_tcp合用的参数都可以设置,在延迟和吞吐量之间来平衡。

祝玩得开心!

Post Footer automatically generated by wp-posturl plugin for wordpress.

Erlang 18RC1释出

April 1st, 2015 1 comment

原创文章,转载请注明: 转载自系统技术非业余研究

本文链接地址: Erlang 18RC1释出

三月底,官网宣布Erlang 18RC1公测,参看 这里,按照惯例Erlang每年会出一个大版本,从R11开始到现在R18,7年时间我从Erlang的发展历程中见证了一个大型系统的演变过程。

Erlang/OTP 18.0-rc1 is available for testing.
This is an alpha release, which will be followed by a planned beta release in May and a final OTP 18.0 product release in June 2015.

18.0正式版本6月份会放出, 这个版本很值得期待的内容有以下几点, 参看 News From the OTP TEAM Berlin Erlang Factory Lite 2014

重点需要解决的:
f1
当期亮点:
f2

长期的:
f3

对于这次预发布最大的亮点如下:

Some highlights of the release are:

dialyzer: The -dialyzer() attribute can be used for suppressing warnings in a module by specifying functions or warning options. It can also be used for requesting warnings in a module.
erts: The time functionality has been extended. This includes a new API for time, as well as “time warp” modes which alters the behavior when system time changes. You are strongly encouraged to use the new API instead of the old API based on erlang:now/0. erlang:now/0 has been deprecated since it will always be a scalability bottleneck. For more information see the Time and Time Correction chapter of the ERTS User’s Guide. Here is a link http://www.erlang.org/documentation/doc-7.0-rc1/erts-7.0/doc/html/time_correction.html

erts: Beside the API changes and time warp modes a lot of scalability and performance improvements regarding time management has been made. Examples are:
scheduler specific timer wheels,
scheduler specific BIF timer management,
parallel retrieval of monotonic time and system time on OS:es that support it.
erts: The previously introduced “eager check I/O” feature is now enabled by default.
erts/compiler: enhanced support for maps. Big maps new uses a HAMT (Hash Array Mapped Trie) representation internally which makes them more efficient. There is now also support for variables as map keys.
ssl: Remove default support for SSL-3.0 and added padding check for TLS-1.0 due to the Poodle vulnerability.
ssl: Remove default support for RC4 cipher suites, as they are consider too weak.
stdlib: Allow maps for supervisor flags and child specs

其中对定时器的API语义和使用方式做了重新定义,伸缩能力优化做了大量的工作,拆成基于每个调度器的,对于定时器密集型的业务会有很大的性能提升。
具体的参考:Erlang VM Developer Lukas Larsson 做的 演讲

这次解决了定时器的瓶颈,个人最期待的是Multiple poll sets, 这个解决了,性能就完美了!

祝玩的开心!

Post Footer automatically generated by wp-posturl plugin for wordpress.

Categories: Erlang探索, 源码分析 Tags: , ,

R17新的调度策略+sub

May 18th, 2014 9 comments

原创文章,转载请注明: 转载自系统技术非业余研究

本文链接地址: R17新的调度策略+sub

R17的release note提到:

OTP-11385 A new optional scheduler utilization balancing mechanism has
been introduced. For more information see the +sub command
line argument.

Characteristics impact: None, when not enabled. When enabled,
changed timing in the system, normally a small overhead due
to measuring of utilization and calculating balancing
information. On some systems, such as old Windows systems,
the overhead can be quite substantial. This time measurement
overhead highly depend on the underlying primitives provided
by the OS.

引入了新的调度策略,具体的实现参见:这里
作者是大名鼎鼎的rickard-green,代码质量一定不会错的。

那这调度器策略干啥的呢?参见erl文档, 写的很清楚了:

+sub true|false
Enable or disable scheduler utilization balancing of load. By default scheduler utilization balancing is disabled and instead scheduler compaction of load is enabled which will strive for a load distribution which causes as many scheduler threads as possible to be fully loaded (i.e., not run out of work). When scheduler utilization balancing is enabled the system will instead try to balance scheduler utilization between schedulers. That is, strive for equal scheduler utilization on all schedulers.

再对比下默认的调度器策略说明,+scl:

+scl true|false
Enable or disable scheduler compaction of load. By default scheduler compaction of load is enabled. When enabled, load balancing will strive for a load distribution which causes as many scheduler threads as possible to be fully loaded (i.e., not run out of work). This is accomplished by migrating load (e.g. runnable processes) into a smaller set of schedulers when schedulers frequently run out of work. When disabled, the frequency with which schedulers run out of work will not be taken into account by the load balancing logic.

就很容易明白,之前的调度策略是先让低ID的调度器忙起来,不够用的话,再把高ID的拉下水,比较节能。但是在某些专机专用的场合,调度器能耗不是重点,希望全部调度器能够参与计算,减少系统的延迟,才是重点。 那这个+sub true就是你想要的。
这个特性唯一依赖的就是高精度时钟,而linux是不缺的, 默认不开启。
写段代码验证下,fib:busy让CPU保持狂运算:

$ cat fib.erl
-module(fib).
-export([fib/1, busy/0]).

fib(0) -> 1;
fib(1) -> 1;
fib(N) -> fib(N-1) + fib(N-2).
busy()-> fib(10), busy().

分别用不同的调度器策略试验下效果, +sbt db绑定CPU,方便观察:

$ erl  +sbt db +sub true 
Erlang/OTP 17 [erts-6.0.1] 1 [64-bit] [smp:16:16] [async-threads:10] [hipe] [kernel-poll:false]

Eshell V6.0.1  (abort with ^G)
1> [spawn(fun()-> fib:busy() end)||_<-lists:seq(1,8)].
[<0.34.0>,<0.35.0>,<0.36.0>,<0.37.0>,<0.38.0>,<0.39.0>,
 <0.40.0>,<0.41.0>]
2> 

不同的策略,CPU使用情况如下图(nmon):
+sub false
nmon1
+sub true
nmon2
效果非常明显。

祝玩的开心。

Post Footer automatically generated by wp-posturl plugin for wordpress.

Erlang内存体系调优

April 28th, 2014 1 comment

原创文章,转载请注明: 转载自系统技术非业余研究

本文链接地址: Erlang内存体系调优

Lukas Larsson,核心的VM开发者,最近很活跃,在Erlang内存体系上做了不少工作,包括recon项目的贡献。
1389811159312570lukas

他最近在erlang factory会议上分享了“Memory Allocators in the VM, Memory Management: Battle Storie”, 参见这里

Erlang内存体系架构是个复杂的体系,一般的开发人员能难一眼就能搞清楚:

memory_architecture

所以我们需要专家的经验把我们迅速带入门,他的PPT不再提供下载,我拉了一份,在 这里,原理、方法以及案例分析,很不错。

祝玩得开心!

Post Footer automatically generated by wp-posturl plugin for wordpress.

Categories: Erlang探索, 调优 Tags: , ,

Erlang公平调度的误解

April 27th, 2014 4 comments

原创文章,转载请注明: 转载自系统技术非业余研究

本文链接地址: Erlang公平调度的误解

Erlang公平调度是它的哲学(或者说坚持)之一,从第一个版本的beam代码的时间片分配和抢占开始,到最近版本的bif对公平性的坚持(比如R17版binary_to_term就大幅做了修改,代码复杂很多,执行效率也有下降,但是在碰到大的binary的情况下,通过Trap机制会让出执行权,排队后再回来断点续作), nif(加入扣除时间片的接口),这些努力保证了erlang系统是个公平的系统。

很多终端系统和业务会受益于这个哲学,如云计算。不管用户大小和业务的负载情况如何,系统性的公平性可以保证每个用户有机会被服务,对用户有很好的体验。 而公平性一定是要贯穿于整个系统里面,特别是有设计哲学方面来保证,每个模块和系统的设计者都能心有默契来遵守。如果有一个人打破了,整个系统其他的公平也就失去意义。这也是为什么公平性这么难做的核心原因。

我们在云业务里面会经常碰到一个系统在服务内部用户的时候效果很好,针对公众服务的时候就遇到各种抱怨。我举个简单的例子如RDS(mysql云),如果不考虑公平性,来一个SQL服务一个,而不管SQL的大小和复杂度,就会马上面临一个问题,强势的几个用户会把这个系统的资源全部占光,其他用户的SQL根本没有机会得到执行。这个问题当然可以通过mysql后端的资源隔离,如cgroup限制CPU,内存,IO,网络的消耗,还需要通过精确的每条SQL的消耗来在适当的时候让出控制权来达到目的。 这个链条上的公平非常难做,所以说大部分的系统都是蹩脚的,无法做到真正的公平,只是程度的差别而已。

虽然Erlang骨子里面就强调公平,而且在身体力行,但是实现上的细节决定了,下面几件事情上做不到公平,留下了坑。我们知道erlang代码核心的思路是根据规约数(函数执行一个,算一个规约),每个进程预先分配比如2000个时间片。时间片用完或者条件不满足(比如需要等消息)时候让出控制权,而且系统是消息驱动的。
Read more…

Post Footer automatically generated by wp-posturl plugin for wordpress.

Categories: Erlang探索 Tags:

Erlang内存分配器之mbcs_pool

April 27th, 2014 1 comment

原创文章,转载请注明: 转载自系统技术非业余研究

本文链接地址: Erlang内存分配器之mbcs_pool

Erlang R17.0 发布的release note 里面花了挺多笔墨讲了内存carrier迁移的特性:

Support for migration of memory carriers between memory allocator instances has been introduced.
By default this feature is not enabled and do not effect the characteristics of the system. When enabled it has the following impact on the characteristics of the system:

* Reduced memory footprint when the memory load is unevenly distributed between scheduler specific allocator instances.
* Depending on the default allocaton strategy used on a specific allocator there might or might not be a slight performance loss.
* When enabled on the fix_alloc allocator, a different strategy for management of fix blocks will be used.
* The information returned from erlang:system_info({allocator, A}), and erlang:system_info({allocator_sizes, A}) will be slightly different when this feature has been enabled. An mbcs_pool tuple will be present giving information about abandoned carriers, and in the fix_alloc case no fix_types tuple will be present.

For more information, see the documentation of the +M acul command line argument.

那么什么是”migration of memory carriers between memory allocator instances“,解决什么问题呢?
官方的文档 erts/emulator/internal_doc/CarrierMigration.md, 见这里, 已经描述的非常清楚了。
allocators-1
我来简单的说下复述下:
Erlang的内存分配器为了提高性能,每个调度器一个都有自己的内存池,在申请/释放内存的可以避免大量的锁争用,提高了性能。但也带来内存浪费的问题,首先调度器默认使用策略是“full load or not”, 也就是说低ID的调度器如果没饱和的话,不会用下一个调度器。在高负载的情况下,更多的调度器被启用,该调度器上的内存被缓冲,留在池子里。当工作负载下去的的话,因为压力没到,高ID的调度器没机会被使用,也就是说这个时候,这个调度器上的内存就浪费掉了,从整个VM的角度来看,内存的碎片率就很高。Erlang的VM是以稳定性著名的,但是它也有Crash的时候,十有八九是因为内存爆了。我们在设计系统的时候,通常从数据量去反推需要的内存,但是如果有碎片或者浪费存在严重的话,我们就无法准确,就可能导致灾难。 为了解决这个问题,最直接的反应就是当每个调度器池子里面的内存使用率低于一定程度的时候,就把该块内存出让出来,让有需要的调度器能够利用起来。这就是内存carriers迁移要解决的核心问题。

这个特性在R16加入的默认不启用,R17默认启用了,也就是说+M acul 默认是“de”. 带来的影响有下面几个:
1. 内存申请的效率,现在的测试是先在自己的池子里面分配,不满足了就找cpool,再不满足才去找mseg或者sys分配器申请。效率和利用率是鱼和熊掌不可兼得。
2. 内存分配器的内存除了在池子里面还有在cpool里,统计内存的时候要小心。
3. 内存浪费率到什么时候被废弃。

Read more…

Post Footer automatically generated by wp-posturl plugin for wordpress.

Categories: Erlang探索 Tags: , , ,