转载:【原译】Erlang性能的八个误区(Efficiency Guide)
转自:http://www.cnblogs.com/futuredo/archive/2012/10/16/2725770.html
The Eight Myths of Erlang Performance
Erlang/OTP R15B02
1 Myth: Funs are slow
Fun函数很慢(这里应该是指Module:Function(Arguments)这种形式的函数,其中M,F,A可以是变量类型,值不是固定的)
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.
是的,fun函数曾经很慢,非常慢,比apply/3方式还慢。最开始,fun函数只是通过编译器策略,普通元组,apply/3方式和其他一些新的东西来实现的。
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.
但是那已经是过去的历史,在R6B版本中,fun函数有了自己的数据结构,在R7B版本中,fun函数进一步做了优化。现在一个fun函数调用的耗费大概在本地函数调用和apply/3方式之间。
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.
现在,编译器把列表解析重新写成一个普通的递归函数。当然,使用一个尾递归函数并且在最后反转效率将更快。是吗?让我们来看看下一个因素。
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.
那种情况在R7B版本之前是对的,在R7B版本中,编译器开始通过使用一个空列表覆写那些将不会被用到的数据引用来产生代码,所以垃圾回收器在没必要的时候就可以不保留那些不需要的值。
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.
在R12B及 以后的版本中,做了一个优化,使得在许多情况下能减小体递归调用时在堆栈上占用的空间,所以一个体递归函数和一个尾递归函数,同样在最后调用 lists:reverse/1函数实现列表反转,所使用的内存空间几乎相等。现在,lists:map/2,lists:filter/2,列表解析, 以及许多其他普通递归函数占用的内存空间跟它们的尾递归实现一样。
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.
根据情况有所不同。在Solaris/Sparc上,体递归函数看起来稍微快一点,即使对于那些有很多元素的列表。在x86架构上,尾递归要比体递归快近30%。
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).
注意:一个不需要在最后反转列表的尾递归函数,当然比一个体递归函数快,尾递归函数不构造任何数据项(例如,一个计算列表中所有整数的和的函数)
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
当然,有经验的Erlang程序员实际上会这样做
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].)
这个略微更有效率,因为你不再构建一个列表元素,只是直接复制它而已。(如果编译器不自动将[H]++Acc重写为[H|Acc],那上面的写法会更有效)
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.
实际上,字符串处理如果做得不适当会显得很慢。在Erlang中,你将不得不稍稍多思考一下字符串是怎样被使用的,并选择一个恰当的展现方式,如果你要用正则表达式,使用re模块,不要用旧的regexp模块。
6 Myth: Repairing a Dets file is very slow
修复一个Dets文件非常慢
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.
现在的修复时间仍然和文件里记录的数目成正比,但是Dets文件的修复在以前要慢很多很多。Dets已经被大量地做了重写和改进。
7 Myth: BEAM is a stack-based byte-code virtual machine (and therefore slow)
BEAM是一个基于堆栈的字节码虚拟机(因此很慢)
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是一个基于寄存器的虚拟机。它有1024个用来存储临时变量和在调用函数时传参的寄存器。在函数调用期间需要存在的变量被保存在堆栈中。
BEAM is a threaded-code interpreter. Each instruction is word pointing directly to executable C-code, making instruction dispatching very fast.
BEAM是一个threaded-code(螺纹代码?)解释器。每条指令直接指向可执行C代码,使得指令调度非常快。
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.
这个以往是正确的,但是自R6B版本以来,BEAM编译器完全有能力注意到有个变量未被使用。
转载:【原译】Erlang性能的八个误区(Efficiency Guide)的更多相关文章
- 转载:【原译】Erlang列表处理(Efficiency Guide)
转自:http://www.cnblogs.com/futuredo/archive/2012/10/22/2734186.html List handling 1 Creating a list ...
- 转载:【原译】Erlang常见注意事项(Efficiency Guide)
转自:http://www.cnblogs.com/futuredo/archive/2012/10/17/2726416.html Common Caveats(常见注意事项) Erlang/OTP ...
- 转载:【原译】Erlang构建和匹配二进制数据(Efficiency Guide)
转自:http://www.cnblogs.com/futuredo/archive/2012/10/19/2727204.html Constructing and matching binarie ...
- 转载:erlang程序优化点的总结
erlang程序优化点的总结(持续更新) 转自:http://wqtn22.iteye.com/blog/1820587 转载请注明出处 注意,这里只是给出一个总结,具体性能需要根据实际环境和需要来确 ...
- 【转载】PHP性能优化干货
PHP优化对于PHP的优化主要是对php.ini中的相关主要参数进行合理调整和设置,以下我们就来看看php.ini中的一些对性能影响较大的参数应该如何设置. # vi /etc/php.ini (1) ...
- 【转载】Spark性能优化指南——高级篇
前言 数据倾斜调优 调优概述 数据倾斜发生时的现象 数据倾斜发生的原理 如何定位导致数据倾斜的代码 查看导致数据倾斜的key的数据分布情况 数据倾斜的解决方案 解决方案一:使用Hive ETL预处理数 ...
- 【转载】 Spark性能优化指南——基础篇
转自:http://tech.meituan.com/spark-tuning-basic.html?from=timeline 前言 开发调优 调优概述 原则一:避免创建重复的RDD 原则二:尽可能 ...
- [转载]U3d常规性能优化技巧
以下技巧并不是必须的,但是对于想要提升游戏性能的人来说应该还是很不错的. 优化的常规技巧 n 剖析你的游戏. 不要花费时间来优化那些晦涩的代码或者缩减图形文件的大小,除非这是你游戏的瓶颈.第一次剖析你 ...
- [转载]Linux服务器性能评估与优化
转载自:Linux服务器性能评估与优化 一.影响Linux服务器性能的因素 1. 操作系统级 CPU 内存 磁盘I/O带宽 网络I/O带宽 2. 程序应用级 二.系统性能评估标准 影响性 ...
随机推荐
- php序列化与反序列化时字符集不一致问题的解决办法
今天的用PHP的时候无意的出现了用unserialize()函数转换老是返回false,我确认我的字符串是没错的,测试了很多次还是一样,没办法,启用了error_reporting(E_ALL)启用错 ...
- 在 IE 浏览器中,使用 bootstrap 使得页面滚动条浮动显示,自动隐藏,自动消失
貌似是从 IE10 开始?为了触屏操作优化浏览器的内容显示,IE 浏览器提供了一种可以浮动显示,自动隐藏的滚动条样式,但是这个样式会在某些情况下造成一些困扰,比如下图... 其实默认情况下,桌面版的 ...
- springmvc+spring+mybatis+maven项目构建
1.首先在myeclipse10中安装maven的插件,将插件放入D:\Program Files (x86)\myEclipse10\MyEclipse Blue Edition 10\dropin ...
- Java生成二维码QRCode.jar
所需jar包:QRCode.jar:http://download.csdn.net/detail/xuxu198899223/7717745 package ewm; import java.awt ...
- java playframework
刚学了java不久就让我们尝试架构,就选择了一个比較简单的架构 play framework直接上图 这里的执行环境是JDK1.7,我试了一下jdk1.8不行出问题了play使用的是play-1.2. ...
- Linux GCC编译库
本文主要解决以下几个问题 1).为什么要使用库? 2).库的分类 3).创建自己的库 为什么要使用库? 或许大家对自己初学 Linux时的情形仍记忆尤新吧.如果没有一个能较好的解决依赖关系的包管理器, ...
- WebForm中使用MVC
http://www.cnblogs.com/encoding/articles/3556046.html ********************************************** ...
- maven install 跳过test方法
方式1:用命令带上参数 mvn install -Dmaven.test.skip=true 方式2:在pom.xml里面配置 <build> <defaultGoal>com ...
- weblogic连接池问题总结(转载)
转自:某局Weblogic 连接池问题(现场报告)(Connection has been administratively disabled. Try later.) 目录 1. 概述 3 1.1 ...
- PhantomJS与CasperJS在Windows下的安装与使用
按照网上的教程来呢,一定是不好使的,这是常理. 所以必须要告诉你怎么使用Phantomjs…… 这么用! 1.下载Phantomjs的压缩包并解压缩: 2.在bin目录(包含phantomjs.exe ...