您的位置:首页 > 其它

erlang的官方文档部分翻译

2012-04-06 16:16 260 查看
erlang的八个秘密

1. 复杂函数Funs较慢

funs的速度比apply/3要慢,它从实现机制上利用了编译器的小伎俩,速度上比apply/3使用元组和大量精巧设计来的慢。

2. 列表解析比较慢

在以前列表解析是使用funs的方式实现的,因此它的速度是非常慢的。

但现在使用递归函数实现,当然,采用尾递归函数,在末尾多加一个列表反转仍然要快很多。这在下一个秘密中会讲到。

3. 尾递归函数比普通递归函数要快得多

普通递归函数在堆栈上留下了废旧对象的指针,垃圾回收器需要将所有的废旧对象拷贝一份。而在尾递归函数中,原地开栈意味着废旧对象直接被弃掉了

以上是R7B 之前的版本的情况,在R7B 版本中,编译器运行一段代码,用空列表覆盖了指向废旧对象的指针,因此垃圾回收器不用将废旧数据一直保留了。

即便采用了上述优化,采用尾递归仍然要比普通递归函数快得多,为什么呢?

这就与递归函数被调用时占据了多少字节的堆栈有关系。在绝大多数情况下,一个普通递归函数会比一个尾递归函数开辟更多字节的堆栈,正因为如此,垃圾回收器需要被更频繁地使用,而且它需要更多的来回访问堆栈。

在R12B以及更后来的版本中,已经减少了递归函数调用对于堆栈字数的使用,所以在R12B以后的版本中,使用普通递归函数与使用尾递归调用函数再在其末尾使用一个lists:reverse/1反转列表这两种方式使用相同多的空间。

既然如此,那么哪一个更快?

看情况,在Solaris/Sparc 中,普通递归函数稍微快,即便在元素比较多的列表处理上。而在X86中,尾递归比普通递归快 30%.

因此在选择时,若你要极大限度的提升速度,就要进行权衡,因为尾递归调用并非在所有环境中都快于普通递归。

当然,在不必在尾部使用lists:reverse/1进行列表反转的情况下,尾递归是毫无疑问快于普通递归的(比如,写一个函数计算列表中所有整数和)

4. ‘++’运算是非常糟糕的

‘++’运算是无论如何不应该存在的,

例如这样的例子:

naive_reverse([H|T]) ->
naive_reverse(T)++[H];

naive_reverse([]) ->
[].
很显然可以改写成这样:

naive_but_ok_reverse([H|T], Acc) ->

naive_but_ok_reverse(T, [H]++Acc);

naive_but_ok_reverse([], Acc) ->

Acc.

实际上经验丰富的程序员应该这样:

vanilla_reverse([H|T], Acc) ->

vanilla_reverse(T, [H|Acc]);

vanilla_reverse([], Acc) ->

Acc.

5. Strings
比较慢

在erlang里面字符串如果处理得不合适将会非常的慢,你需要根据字符串是如何处理的合理地选择 re.erl 模块取代 regexp 模块。

6. 整理 Dets文件非常慢

整理时间与文件中存在的record 数量成正比。

7. BEAM 是一个基于堆栈的字节码的虚拟机(因此慢)

8. 当变量不使用的时候,用‘_’提高程序的速度

这个是之前的优化方法,自从R6B之后编译器就能自动识别不使用的变量了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: