天天看點

轉載:【原譯】Erlang常見注意事項(Efficiency Guide)Common Caveats(常見注意事項)

轉自:http://www.cnblogs.com/futuredo/archive/2012/10/17/2726416.html

Erlang/OTP R15B02

  Here we list a few modules and BIFs to watch out for, and not only from a performance point of view.

  這裡我們列出了需要注意的一些子產品和内置函數,不僅僅是從性能的角度來看。

  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來生成定時器比用timer子產品提供的定時器效率要高的多。 timer子產品使用一個分離的程序來管理定時器,而且如果很多程序頻繁地建立和取消這些計時器(特别是當使用SMP模拟器時),那個管理程序很容易負載過 重。

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

  那些在timer子產品中的不用來管理定時器的函數(例如,timer:tc/3,timer:sleep/1),不調用timer-server程序,是以是無害的。

  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),模拟器會終止。

  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_existing_atom/1函數,來防範denial-of-service攻擊(拒絕服務攻擊)。(所有被允許的原子必須先建立 好,比如在一個子產品中使用,然後再加載那個子產品)

  Using list_to_atom/1 to construct an atom that is passed to apply/3 like this

  像下面這樣使用list_to_atom/1函數來建構一個原子,然後傳給apply/3

  is quite expensive and is not recommended in time-critical code.

  代價相當大,在時間因素很重要的代碼裡不推薦這樣使用。

  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.

  計算清單長度的時間和這個清單的長度成正比,相反的,tuple_size/1,byte_size/1,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來有效實作的。盡管如此,在時間因素很重要的代碼裡,如果輸入的清單有可能會非常長,你仍然可能會避免使用它。

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

  一些length/1函數的使用情況可以用比對來替代。比如,下面代碼

  can be rewritten to

  可以被重寫成

  (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.)

  (一點輕微的不同在于,如果輸入L是個不合适的清單,length(L)會執行失敗,但是第二個代碼塊中的比對方法能夠接收不合适的清單)

  setelement/3 copies the tuple it modifies. Therefore, updating a tuple in a loop usingsetelement/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/3will be replaced with a special destructive setelement instruction. In the following code sequence

  對于這種複制元組的規則,有一個例外。如果編譯器可以清楚的知道,這種破壞性的更新會産生跟複制一樣的結果,那麼一種特殊的setelement指令會代替原有的對setelement/3函數調用。下面的代碼序列中

  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 onesetelement/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例子一樣建構代碼,在一個大型的元組中修改多個元素的最佳方式就是,把元組轉換成一個清單,修改清單,再把清單改回成元組。

  size/1 returns the size for both tuples and binary.

  size/1函數傳回元組或者二進制串的大小。

  Using the new BIFs tuple_size/1 andbyte_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版本中新引入的内置函數tuple_size/1和byte_size/1,能夠讓編譯器和虛拟機做更多的優化。進一步的優點就是新的内置函數能夠幫助Dialyzer發現程式中更多的bug。

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

  相比較調用split_binary/2函數來分解一個二進制串而言,比對通常更加有效。而且,混合使用bit文法比對和split_binary/2函數,可能會阻礙某些bit文法比對的優化工作。

  DO

  DO NOT

  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:

  注意,'--'操作符的複雜度和它的操作數的長度的乘積成正比,這表示,如果兩個操作數是長清單,那麼它的處理會很慢:

  Instead use the ordsets module:

  要使用ordsets子產品:

  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:

  很顯然,如果原來的清單中元素的順序很重要,那麼上面的代碼是行不通的。如果清單中元素的順序必須保留,那麼像這樣做:

  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:如果清單中包含重複的元素,那麼這塊代碼跟'--'操作符的效果不同。(HugeList2中出現一個元素即會删掉HugeList1中所有重複的這個元素)

  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

繼續閱讀