免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 2479 | 回复: 1
打印 上一主题 下一主题

[技术动态] erlang 17性能话题 [复制链接]

论坛徽章:
27
水瓶座
日期:2014-08-22 21:06:34程序设计版块每日发帖之星
日期:2015-11-25 06:20:0015-16赛季CBA联赛之新疆
日期:2015-12-19 19:05:48IT运维版块每日发帖之星
日期:2015-12-25 06:20:31IT运维版块每日发帖之星
日期:2015-12-25 06:20:31IT运维版块每日发帖之星
日期:2015-12-25 06:20:3315-16赛季CBA联赛之上海
日期:2016-04-15 19:51:31程序设计版块每日发帖之星
日期:2016-04-17 06:23:29程序设计版块每日发帖之星
日期:2016-04-23 06:20:00程序设计版块每日发帖之星
日期:2016-05-26 06:20:00每日论坛发贴之星
日期:2016-05-26 06:20:0015-16赛季CBA联赛之辽宁
日期:2017-02-16 23:59:47
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2014-10-03 21:34 |只看该作者 |倒序浏览
The Eight Myths of Erlang Performance

Some truths seem to live on well beyond their best-before date, perhaps because "information" spreads more rapidly from person-to-person faster than a single release note that notes, for instance, that funs have become faster.

Here we try to kill the old truths (or semi-truths) that have become myths.

2.1  Myth: Funs are slow

Yes, funs used to be slow. Very slow. Slower than apply/3. Originally, funs were implemented using nothing more than compiler trickery, ordinary tuples, apply/3, and a great deal of ingenuity.

But that is ancient history. Funs was given its own data type in the R6B release and was further optimized in the R7B release. Now the cost for a fun call falls roughly between the cost for a call to local function and apply/3.

2.2  Myth: List comprehensions are slow

List comprehensions used to be implemented using funs, and in the bad old days funs were really slow.

Nowadays the compiler rewrites list comprehensions into an ordinary recursive function. Of course, using a tail-recursive function with a reverse at the end would be still faster. Or would it? That leads us to the next myth.

2.3  Myth: Tail-recursive functions are MUCH faster than recursive functions

According to the myth, recursive functions leave references to dead terms on the stack and the garbage collector will have to copy all those dead terms, while tail-recursive functions immediately discard those terms.

That used to be true before R7B. In R7B, the compiler started to generate code that overwrites references to terms that will never be used with an empty list, so that the garbage collector would not keep dead values any longer than necessary.

Even after that optimization, a tail-recursive function would still most of the time be faster than a body-recursive function. Why?

It has to do with how many words of stack that are used in each recursive call. In most cases, a recursive function would use more words on the stack for each recursion than the number of words a tail-recursive would allocate on the heap. Since more memory is used, the garbage collector will be invoked more frequently, and it will have more work traversing the stack.

In R12B and later releases, there is an optimization that will in many cases reduces the number of words used on the stack in body-recursive calls, so that a body-recursive list function and tail-recursive function that calls lists:reverse/1 at the end will use exactly the same amount of memory. lists:map/2, lists:filter/2, list comprehensions, and many other recursive functions now use the same amount of space as their tail-recursive equivalents.

So which is faster?

It depends. On Solaris/Sparc, the body-recursive function seems to be slightly faster, even for lists with very many elements. On the x86 architecture, tail-recursion was up to about 30 percent faster.

So the choice is now mostly a matter of taste. If you really do need the utmost speed, you must measure. You can no longer be absolutely sure that the tail-recursive list function will be the fastest in all circumstances.

Note: A tail-recursive function that does not need to reverse the list at the end is, of course, faster than a body-recursive function, as are tail-recursive functions that do not construct any terms at all (for instance, a function that sums all integers in a list).

2.4  Myth: '++' is always bad

The ++ operator has, somewhat undeservedly, got a very bad reputation. It probably has something to do with code like

DO NOT

naive_reverse([H|T]) ->
    naive_reverse(T)++[H];
naive_reverse([]) ->
    [].
which is the most inefficient way there is to reverse a list. Since the ++ operator copies its left operand, the result will be copied again and again and again... leading to quadratic complexity.

On the other hand, using ++ like this

OK

naive_but_ok_reverse([H|T], Acc) ->
    naive_but_ok_reverse(T, [H]++Acc);
naive_but_ok_reverse([], Acc) ->
    Acc.
is not bad. Each list element will only be copied once. The growing result Acc is the right operand for the ++ operator, and it will not be copied.

Of course, experienced Erlang programmers would actually write

DO

vanilla_reverse([H|T], Acc) ->
    vanilla_reverse(T, [H|Acc]);
vanilla_reverse([], Acc) ->
    Acc.
which is slightly more efficient because you don't build a list element only to directly copy it. (Or it would be more efficient if the the compiler did not automatically rewrite [H]++Acc to [H|Acc].)

2.5  Myth: Strings are slow

Actually, string handling could be slow if done improperly. In Erlang, you'll have to think a little more about how the strings are used and choose an appropriate representation and use the re module instead of the obsolete regexp module if you are going to use regular expressions.

2.6  Myth: Repairing a Dets file is very slow

The repair time is still proportional to the number of records in the file, but Dets repairs used to be much, much slower in the past. Dets has been massively rewritten and improved.

2.7  Myth: BEAM is a stack-based byte-code virtual machine (and therefore slow)

BEAM is a register-based virtual machine. It has 1024 virtual registers that are used for holding temporary values and for passing arguments when calling functions. Variables that need to survive a function call are saved to the stack.

BEAM is a threaded-code interpreter. Each instruction is word pointing directly to executable C-code, making instruction dispatching very fast.

2.8  Myth: Use '_' to speed up your program when a variable is not used

That was once true, but since R6B the BEAM compiler is quite capable of seeing itself that a variable is not used.

论坛徽章:
12
射手座
日期:2014-10-02 11:31:29程序设计版块每日发帖之星
日期:2016-05-28 06:20:00每日论坛发贴之星
日期:2016-05-27 06:20:00程序设计版块每日发帖之星
日期:2016-05-27 06:20:00程序设计版块每日发帖之星
日期:2016-05-25 06:20:00每日论坛发贴之星
日期:2016-05-24 06:20:00程序设计版块每日发帖之星
日期:2016-05-24 06:20:0015-16赛季CBA联赛之深圳
日期:2016-05-23 15:33:59程序设计版块每日发帖之星
日期:2016-05-20 06:20:00程序设计版块每日发帖之星
日期:2016-04-26 06:20:00神斗士
日期:2015-12-03 09:27:3215-16赛季CBA联赛之八一
日期:2016-12-29 09:56:05
2 [报告]
发表于 2014-10-10 09:59 |只看该作者
Erlang,确实,性能有点迷惑。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP