`
zhongwencool
  • 浏览: 28287 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

erlang efficient guide 3

阅读更多

* 3 Common Caveats
* 3常见的注意事项


Here we list a few modules and BIFs to watch out for, and not only from a performance point of view.
下面我们来看-看erlang的一些常用module和bif,不仅仅从性能的角度去考虑。

3.1 The timer module
3.1 timer模块


  • Creating timers using erlang:send_after/3 and erlang:start_timer/3 is much more efficient than using the timers provided by the timer module. The timer module uses a separate process to manage the timers, and that process can easily become overloaded if many processes create and cancel timers frequently (especially when using the SMP emulator).

  • 使用erlang:send_after/3 和erlang:start_timer/3会比使用time模块内的函数高效得多。timer 模块使用一个独立的进程来管理时间,这个进程如果大量的进程频繁去创建和取消时间很容易就超负荷了(特别是使用SMP方式的时候)


  • The functions in the timer module that do not manage timers (such as timer:tc/3 or timer:sleep/1), do not call the timer-server process and are therefore harmless.

  • 有一些timer内不管理时间定时器的函数(例如:timer:tc/3, timer:sleep/1),不去调用定时器server进程的函数都是无害的。【也就是说:有些timer里面的函数是不依赖于这个server的,可以随意用】
  • 【附】关于erlang:send_after/3与erlang:send_time/3的区别【cancle_timer/1只能去掉那些没有超时的信息,没发出去的】
  • http://www.cnblogs.com/me-sa/archive/2012/03/16/erlang-timer.html
  • 这时候send_after里面存放的是Msg, 那用户如何知道Msg是对于那个TimerRef的呢? 读者可能说, 那我可以在消息里面加入TimerRef. 这个主意不错, 但是问题是在send_after调用返回之前, 你是无法得到TimerRef, 当然也就无从构造这个消息, 那就无法处理这个可能的超时信息, 就会破坏逻辑.
  • 所以erts version 5.4.11 引入了, start_timer来解决这个问题. 它是自动的在超时后, 要发送消息前, 在消息里面添加了{timeout, TimerRef, Msg}, 达到识别的目的


  • erlang使用timer有3中方式:
  • 1. 语法层面的 receive ... after ...
  •    这个是opcode实现的,一旦timeout立即把process加到调度队列,使用频度比较高。
  • 2. bif 
  •    erlang:send_after(Time, Dest, Msg) -> TimerRef
  •    erlang:start_timer(Time, Dest, Msg) -> TimerRef
  •    这个一旦timeout就给Dest发送一条消息,使用频度不是很高。
  • 3.driver层面的。
  •    int driver_set_timer(ErlDrvPort port, unsigned long time);
  •    inet_driver大量使用这个api. tcp/udp进程需要超时处理,所以有大量的连接的时候这种timer的数量非常大。定时器超时后把port_task加到调度队列。
  • 定时器的最早超时时间用于poll的等待时间。
  • 整个定时器由bump_timer来驱动。bump_timer是在schedule的时候不定期调用的。总之使用timer的时候要小心,因为timer实在scheduler的线程里面调用的,不能做非常耗时的操作,否则会阻塞调度器。
  • 【因为项目中有大量的秒循环,,如果可以使用一个总的send_after/3来给驱动各个子的秒循环(用一个管理秒循环的每秒给各服务发一个信息,来做比较自己服务器起一个erlang:send_after/3),就不用频繁的调用erlang:send_after/3了,听项目负责人是这样说的。但是没去看。。。。。】
  • Ps 最后一篇的erl -s module func arg1 arg2 很吊哦。

3.2 list_to_atom/1
3.2 list_to_atom/1
  • Atoms are not garbage-collected. Once an atom is created, it will never be removed. The emulator will terminate if the limit for the number of atoms (1048576 by default) is reached
  • .

  • 原子是不会被垃圾回收器回收的,原子一旦创建,不会被移除,如果原子的数量达到最大值(默认为1048576 )emulator(模拟器?)就会挂掉。

  • Therefore, converting arbitrary input strings to atoms could be dangerous in a system that will run continuously. If only certain well-defined atoms are allowed as input, you can use list_to_existing_atom/1 to guard against a denial-of-service attack. (All atoms that are allowed must have been created earlier, for instance by simply using all of them in a module and loading that module.)

  • 所以,将任意字符串转化为原子在一个持续动作的系统时是非常危险的。如果只有定义好的原子能够作为输入,你可以使用list_to_exiting_atom/1来作为一种避免出现危机的手段。(所以的允许的原子必须创建早些,比如:通过简单的定义所有的原子在同一模块并加载此模块来实现。)

  • Using list_to_atom/1 to construct an atom that is passed to apply/3 like this
  • apply(list_to_atom("some_prefix"++Var), foo, Args)

  • 以上是错的行为:
  • is quite expensive and is not recommended in time-critical code.
  • 在apply/3的参数中使用list_to_atom/1把string(也是一种list)转化为原子来调用。是非常耗性能的,非常不推荐啊

3.3 length/1
3.3 length/1求列表长

  • The time for calculating the length of a list is proportional to the length of the list, as opposed to tuple_size/1, byte_size/1, and bit_size/1, which all execute in constant time.

  • 执行length/1的时间取决于列表的长度,矶tuple_size/1,byte_size/1, and bit_size/1则是一个固定的值

  • Normally you don't have to worry about the speed of length/1, because it is efficiently implemented in C. In time critical-code, though, you might want to avoid it if the input list could potentially be very long.

  • 正常情况下,你不用担心length/1的执行速度,因为他是用c写的高效代码,在关键性的代码时,一定要禁止在列表很长的时候调用length/1。

  • Some uses of length/1 can be replaced by matching. For instance, this code

  • 一些用length/1的地方可以用模式匹配来做,例如:

foo(L) when length(L) >= 3 ->
    ...

can be rewritten to

foo([_,_,_|_]=L) ->
  ...

  • (One slight difference is that length(L) will fail if the L is an improper list, while the pattern in the second code fragment will accept an improper list.)

  • (一点不同之处在于:length(L)会在L不是一个正当的列表时失败,而第二种情况则能适应不正当的列表。)


3.4 setelement/3
3.4 setelement/3 setelement(Index, Tuple1, Value) -> Tuple2


  • setelement/3 copies the tuple it modifies. Therefore, updating a tuple in a loop using setelement/3 will create a new copy of the tuple every time.

  • setelement/3 会复制那个要修改的元组,在每一次更新用setelement/3都会创建一个新的元组哦。


  • There is one exception to the rule that the tuple is copied. If the compiler clearly can see that destructively updating the tuple would give exactly the same result as if the tuple was copied, the call to setelement/3 will be replaced with a special destructive setelement instruction. In the following code sequence

  • 不会复制的唯一例外:当编译器清楚知道更新后的元组和原来一样时,那么使用setelement/3会被一种特殊的setelement 结构所替代,请看下面的代码

multiple_setelement(T0) ->
    T1 = setelement(9, T0, bar),
    T2 = setelement(7, T1, foobar),
    setelement(5, T2, new_value).

  • the first setelement/3 call will copy the tuple and modify the ninth element. The two following setelement/3 calls will modify the tuple in place.
  • 第一个setelement/3函数会复制元组并修改第九个元素。后面两个setelement/3函数会直接修改这个元组。

  • For the optimization to be applied, all of the followings conditions must be true:

  • 要让上面的优化起作用,下面的原则是要必须遵守的:


  • * The indices must be integer literals, not variables or expressions.
  • * The indices must be given in descending order.
  • * There must be no calls to other function in between the calls to setelement/3.
  • * The tuple returned from one setelement/3 call must only be used in the subsequent call to setelement/3.
  • * 索引必须是一个合法的数字,不是变量,或表达式
  • * 索引必须是降序的
  • * 在使用setelement/3的中间不要调用其它任务函数
  • * 一个setelement/3后面的结果必然是下一个setelement/3的输入

  • If it is not possible to structure the code as in the multiple_setelement/1 example, the best way to modify multiple elements in a large tuple is to convert the tuple to a list, modify the list, and convert the list back to a tuple.

  • multiple_setelement/1 的例子并不多见,修改元组中的多个元素通常的情况是:把一个大的元组转化为一个列表,然后修改列表,再转化为元组。

3.5 size/1
3.5 size/1

  • size/1 returns the size for both tuples and binary.
  • size/1求元组和二进制的大小

  • Using the new BIFs tuple_size/1 and byte_size/1 introduced in R12B gives the compiler and run-time system more opportunities for optimization. A further advantage is that the new BIFs could help Dialyzer find more bugs in your program.

  • 使用R12B更新的BIFs tuple_size/1 和byte_size/1 会让运行时系统更加高效,使用新的bifs的一个长久的优点在于Dialyzer 可以帮助程序发现更多隐藏的bug.

3.6 split_binary/2
3.6 split_binary/2

  • It is usually more efficient to split a binary using matching instead of calling the split_binary/2 function. Furthermore, mixing bit syntax matching and split_binary/2 may prevent some optimizations of bit syntax matching.

  • 使用比特语法来分离二进制比用split_binary/2更加高效,更进一步来讲,混合使用比特语法和split_binary/2会把编译器弄sb的(不会进行相关的优化任务了)

DO

      
 <<Bin1:Num/binary,Bin2/binary>> = Bin,

DO NOT

      
 {Bin1,Bin2} = split_binary(Bin, Num)

3.7 The '--' operator
3.7 “--”操作符

  • Note that the '--' operator has a complexity proportional to the product of the length of its operands, meaning that it will be very slow if both of its operands are long lists:

  • Note: "--"操作符非常依赖于列表的长度,长度越长越慢!
DO NOT

      
 HugeList1 -- HugeList2

Instead use the ordsets module:

DO
        HugeSet1 = ordsets:from_list(HugeList1),
        HugeSet2 = ordsets:from_list(HugeList2),
        ordsets:subtract(HugeSet1, HugeSet2)


  • Obviously, that code will not work if the original order of the list is important. If the order of the list must be preserved, do like this:

  • 显然,上面的代码不能保证原来列表的顺序,如果要保留,则用下面的代码:
DO

    
Set = gb_sets:from_list(HugeList2),
        [E || E <- HugeList1, not gb_sets:is_element(E, Set)]


  • Subtle note 1: This code behaves differently from '--' if the lists contain duplicate elements. (One occurrence of an element in HugeList2 will remove all occurrences in HugeList1.)

  • 注意事项1:这与--不同的在于:如果原列表中有重复的元素都会被移除

  • Subtle note 2: This code compares lists elements using the '==' operator, while '--' uses the '=:='. If that difference is important, sets can be used instead of gb_sets, but note that sets:from_list/1 is much slower than gb_sets:from_list/1 for long lists.

  • 注意事项2:这使用'=='来比较列表元素,而'--'操作符使用'=:='来比较列表元素。如果这个区别显得很重要,那么可以用sets模块来替代gb_sets模块,但是记住,对于长列表,sets:from_list/1函数比gb_sets:from_list/1函数要慢得多。

  • Using the '--' operator to delete an element from a list is not a performance problem:

  • 使用 --来删除列表中的一个元素是没的性能问题的。

OK

      
 HugeList1 -- [Element]

Copyright © 2001-2013 Ericsson AB. All Rights Reserved.


  • 大小: 17.3 KB
分享到:
评论

相关推荐

    Efficiency Guide (erlang)

    ### 效率指南(Erlang) #### 1.1 引言 ##### 1.1.1 目的 本指南旨在帮助Erlang程序员理解如何编写高效、清晰且结构良好的代码。正如Donald E. Knuth所言,“过早优化是一切罪恶之源”,我们强调应该首先关注代码...

    erlang学习相关资料

    Joe的那篇erlang论文 Programming Erlang + 源码包 Erlang Programming Concurrent Programming in Erlang efficiecy guide 资源齐全.希望能帮到你.

    Erlang23_3.zip

    在"Erlang23_3"这个压缩包中,我们可以推测这包含了Erlang的第23个主要版本的第三个修订版。通常,软件版本号的格式是主版本号.次版本号.修订号,所以这里可能是Erlang的稳定版本。该版本可能包含性能优化、新功能、...

    erlang编程 Introducing Erlang

    ### 3. OTP(Open Telecom Platform) OTP是Erlang的开源框架,提供了一套标准库和设计模式,用于构建可维护、可扩展的应用。它包括行为(如GenServer、GenEvent和Supervisor)、应用和系统结构的指导原则,以及...

    erlang25.0 windows版本

    3. **环境变量**:安装过程中,安装程序可能会自动添加Erlang的bin目录到系统的PATH环境变量中,确保命令行可以识别`erl`等Erlang命令。 4. **验证**:安装完成后,打开命令行窗口并输入`erl`,如果Erlang成功安装,...

    inside Erlang VM3

    ### Erlang VM (Erlang虚拟机)深入解析 #### Erlang简介 Erlang是一种通用、并发、强容错的编程语言,最初由爱立信公司开发,旨在解决电信系统的高并发、高可靠需求。它运行在Erlang虚拟机(Erlang Virtual Machine...

    erlang_版本24.3.4.4

    3. **编译Erlang**:进入解压后的目录,运行`./configure`命令来配置编译选项。这一步会检测你的系统环境并生成适合的Makefile。 4. **构建和测试**:执行`make`命令开始编译Erlang。这个过程可能需要一些时间,...

    erlang22最新下载包

    3. **错误修复**:Erlang22.1可能会包含一系列错误修复,确保代码的稳定性和可靠性。 4. **库和工具的更新**:OTP中的各种库(如Mnesia数据库、ERTS(Erlang Run-Time System)和其他并发工具)可能进行了升级,以...

    erlang资源

    3. **错误处理与容错**:Erlang推崇“let it crash”哲学,鼓励程序在遇到错误时快速失败并重启,而不是尝试修复。书里可能会讨论如何构建健壮的系统,利用Erlang的故障隔离特性。 4. **分布式编程**:Erlang进程...

    Erlang官网下载过慢

    3. 更换下载时间:避开网络高峰期进行下载。 4. 镜像站点:寻找Erlang的镜像站点,这些站点通常位于地理位置更近的地方,下载速度会更快。 标签中提到了“Erlang Rabbit 异步通讯”,这意味着讨论的重点是Erlang...

    Erlang/OTP 26.2.1

    Erlang/OTP 26.2.1,Erlang,OTP,26.2.1

    ErlangB和ErlangC计算工具(exe可执行文件+excel两个)

    Erlang B和Erlang C是电信领域中两种重要的流量模型,用于预测和分析通信系统中的呼叫处理能力和拥塞情况。这两个模型由丹麦工程师Agner Krarup Erlang在20世纪初提出,至今仍广泛应用于现代通信网络的设计与优化。 ...

    xiandiao_erlang_Erlang课后习题_

    3. **热代码更新**:Erlang支持运行时代码替换,无需停止服务即可更新和修复应用程序,这在实时系统中非常有用。 4. **容错性**:Erlang的进程模型鼓励设计出可以失败并从中恢复的系统。当一个进程出错时,它不会...

    Erlang 20.3linux安装包

    3. **安装**:进入解压后的目录,然后运行安装脚本。 ```bash cd erlang/20.3 ./install.sh ``` 4. **配置环境变量**:安装完成后,需要将Erlang的bin目录添加到系统的PATH环境变量中,这样可以在任何地方运行...

    Erlang的那几本书

    Programming Erlang + 源码包 Erlang Programming Concurrent Programming in Erlang Joe的那篇erlang论文 efficiecy guide

    Erlang26-windows安装包

    OpenSSL 3 support in Erlang is considered to be mature and ready for production use. Erlang 26.1 and later versions supports FIPS mode on OpenSSL 3 3.12.13 3.12.12 3.12.11 3.12.10 25.0 26.2.x The ...

    erlang安装包.zip

    erlang安装包

    erlang9.rar

    Erlang是一种高级编程语言,特别适用于并发、分布式和实时计算系统。它的设计目标是创建一个高可用性、容错性强、低延迟的系统。Erlang9指的是Erlang/OTP(Open Telephony Platform)的第9个主要版本。OTP是Erlang...

    erlang programming

    3. **分布式系统**:“面对软件错误构建可靠的分布式系统.pdf”强调了Erlang在构建分布式系统时的优势。Erlang提供了一套完整的工具和库,如分布式节点、分布式进程、分布式数据库和分布式故障恢复机制,使得开发者...

    erlang otp25 win安装包

    erlang otp25 win安装包

Global site tag (gtag.js) - Google Analytics