• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            教父的告白
            一切都是紙老虎
            posts - 82,  comments - 7,  trackbacks - 0
            以下是在erlang項(xiàng)目開發(fā)中的一些記錄,即包含很多通俗易懂的原則,也包含一些似是而非的建議,比較混亂,還沒有積累到一個可以分門別類的地步,各位就將就看吧..
            :)

            * 確保沒有任何編譯警告

            * Erlang中String采用list實(shí)現(xiàn),32位系統(tǒng)中,其1個字符用8個字節(jié)的空間(4個保存value, 4個保存指針)。因此string速度較慢,空間占用較大

            * 在Server中,總是盡力書寫尾遞歸(tail-recursive)的函數(shù)

            * 使用'++'時,left list會被拷貝,然后添加到right list的頭部,因此最好把length較短的list放在左側(cè)

            * 避免使用regexp,如果需要正則表達(dá)式,請使用re

            * timer模塊的大部分函數(shù)實(shí)現(xiàn),依賴于一個process,如果過多使用timer,會導(dǎo)致這個process負(fù)載過大,影響效率。
              推薦使用erlang:send_after/3及erlang:start_timer/3

            * 避免使用list_to_atom/1,因?yàn)?span id="xjvxjpf" class="hilite1">erlang中atom數(shù)量最大為1048576, 且不進(jìn)行GC控制。因此如果持續(xù)性的調(diào)用list_to_atom/1
              可能很容易達(dá)到系統(tǒng)上限,從而導(dǎo)致emulator terminate。請使用list_to_existing_atom/1。

            * list內(nèi)部實(shí)現(xiàn)為一個列表,因此length(List), 需要遍歷整個list比較耗時

            * 對于不同的數(shù)據(jù)類型,使用不同的size函數(shù):tuple_size/1, byte_size/1, bit_size/1

            * 使用binary match來進(jìn)行binary的分割,而不使用split_binary/2

            * 如果兩個list都擁有很多數(shù)據(jù),那么請不要使用'--',而是將數(shù)據(jù)轉(zhuǎn)化到ordsets,然后調(diào)用ordsets:substract/2.

            * 對于binary相關(guān)操作可以進(jìn)行binary優(yōu)化(bin_opt_info編譯選項(xiàng))代碼框架:

            *   f(<<Pattern1,...,Rest/bits>>,...) -> 
                   ... % Rest is not used here 
                   f(Rest,...); 
                f(<<Pattern2,...,Rest/bits>>,...) -> 
                  ... % Rest is not used here 
                  f(Rest,...); 
                ... 
                f(<<>>, ...) -> 
                  ReturnValue.

            * 調(diào)用lists:flatten/1可以將list扁平化,這個操作代價很大,比'++'還要昂貴。下面這些時候我們可以避免:
                將數(shù)據(jù)發(fā)送給port時
                調(diào)用list_bo_binary/1和iolist_to_binary前

            * 小的函數(shù)可以讓您方便的找出錯誤的函數(shù)和代碼

            * 不要在同一行出現(xiàn)相同的符號
            20    some_fun() ->
            21       L = [{key1, v1}, {key2, [some_record#v21, v22]}],
            22      ...
            編譯時,會提示line 21 '[' 語法錯誤, 因?yàn)?1行有多個 '[' ,所以這個bug不能準(zhǔn)確定位,你需要花時間去排查代碼。
            好的做法是:
            20 some_fun() ->
            21      L = [{key1, v1},
            22            {key2, [some_record#v21, v22]}
            23            ],
                  ...
            這樣,編譯其會提示你 line 22 '[' 語法錯誤,你很開就知道是那個地方錯了。

            * 使用 CTRL + \ 或 init:stop(), 可以退出Erlang, 使用CTRL + G 及 CTRL + C 彈出菜單選項(xiàng),可以選擇是否退出Erlang
            其中CTRL + G可以用來連接其他的shell, CTRL + C可以查看其他一些系統(tǒng)信息
            Ctrl + C abort 是野蠻的退出方式

            * use "open_port({fd,0,2}, [out])" make erlang program write standard error to unix system

            * If you don't run experiments before you start designing a new system, your entire system will be an experiment!

            * standard data structure desc:

            Module Description
            sets sets, i.e. a collection of unique elements.
            gb_sets sets, but based on a general balanced data structure
            gb_tree a general balanced tree
            dict maps, also called associative arrays
            ets hash tables and ordered sets (trees)
            dets on-disk hash tables

            Suggestion:
            elments count: 0 - 100 | 100 - 10000  |  10000 -
            our select   :  list   |      ets     |  gb_tree

            * 通過code:clash/0 檢測代碼中是否有module沖突現(xiàn)象(sticky)

            * epmd -d -d 啟動 epmd 可以查看erlang node之間的通訊

            * 將正常的邏輯代碼和錯誤處理代碼分離,發(fā)生錯誤時,盡管錯誤。由另一個錯誤處理模塊進(jìn)行處理

            * 類似于操作系統(tǒng),我們的程序也可以分為kernel 和 user 兩層, 對于kernel絕對不能出現(xiàn)錯誤, 對于user可以出現(xiàn)錯誤,進(jìn)行恢復(fù)

            * process頂層loop涉及的代碼及函數(shù),最好在一個module中實(shí)現(xiàn)

            * process 的register name和module名稱一致, 便于尋找代碼

            * 每個process具有一個單一的角色,比如:supervisor 用來進(jìn)行錯誤恢復(fù), work 工作者,可以出現(xiàn)錯誤, trusted worker 不會出現(xiàn)錯誤

            * 通過函數(shù)調(diào)用可以實(shí)現(xiàn)的功能,就不要使用sever實(shí)現(xiàn)(如gen_server, 及類似的loop 實(shí)現(xiàn))

            * 給消息加一個tag,在發(fā)生錯誤的時候,可以定位到消息,同時也有利于程序的穩(wěn)健

            * 在消息循環(huán)中,對于unknown的消息,請調(diào)用lib:flush_receive/0 將其清除,減輕process msg queue的長度

            * server中總是書寫尾遞歸的循環(huán)

            * 盡量使用record, 而不是原始的tuple來表現(xiàn)數(shù)據(jù)結(jié)構(gòu), 在使用record時,使用select match:
            #person{name = Name, age = Age} = Person

            * 對于返回值,最好也添加一個tag,用來說明返回值類型,或者執(zhí)行成功與否

            * 盡可能少的使用catch和try,在erlang程序中,不推薦主動捕獲異常。只有當(dāng)我們的邏輯特別復(fù)雜,我們可以使用throw來返回數(shù)據(jù),使用catch來獲取返回值。

            * 當(dāng)然程序與外界交互,外界數(shù)據(jù)不可靠時,需要使用catch和try

            * 慎重使用process dictory, 當(dāng)你使用get/1, put/1時,你的應(yīng)用會具有很大的slide effect。可以通過加入一個新的參數(shù)來保存原本需要存儲到process dictory中數(shù)據(jù)

            * 如果不想使自己糊涂,請不要使用import

            * 使用export時,將功能類似的接口組合在一起,并添加合理的注視,這樣你的接口更清晰,別人使用起來更方便

            * 不要書寫嵌套太深的代碼

            * 不要書寫太長的module

            * 不要書寫太長的函數(shù)

            * 每行代碼不能太長

            * 避免使用 "_" 匿名變量,請為每個變量選擇有意義的名稱,如夠某個變量暫時不使用,請以下劃線 "_" 開始

            * {error, enfile} enfile error in socket 是以為內(nèi)linux系統(tǒng)中 ulimit 限制, 在root下修改:ulimit -n 25000

            * {error, enotconn} 表示socket已經(jīng)關(guān)閉

            * 在erlang開發(fā)時,慎重使用macro,因?yàn)?span id="nxxrdjz" class="hilite1">erlang的single assign的緣故,同時調(diào)用某個marco,而macro又定義了某個變量,可能導(dǎo)致badmatch錯誤。
            比如:
            -define(ADDLINEINFO1(F),
                    (
                    begin
                    Str1 = lists:concat(["[Mod:", ?MODULE, " Line:", ?LINE, "]"]),
                    Str1 ++ F
                    end
                    )).
            -define(WARN(Log, F, D), log4erl:warn(Log, ?ADDLINEINFO(F), D)).
            如果連續(xù)使用 WARN, 會出現(xiàn)此錯誤

            * erlang中可以定義很多環(huán)境變量:
            ERL_MAX_ETS_TABLES 設(shè)置最大的ets數(shù)目 默認(rèn)1400
            ERL_MAX_PORTS erlang最大的port數(shù)目 默認(rèn)1024

            * .app文件中的start_phases, 選項(xiàng)既可以用來作為include applications之間的同步啟動,也可以用來對單個application進(jìn)行分布啟動。
            順序如下
            包含included app:

            application:start(prim_app)
            => prim_app_cb:start(normal, [])
            => prim_app_cb:start_phase(init, normal, [])
            => prim_app_cb:start_phase(go, normal, [])
            => incl_app_cb:start_phase(go, normal, [])
            ok

            無included app:
            application:start(prim_app)
            => prim_app_cb:start(normal, [])
            => prim_app_cb:start_phase(init, normal, [])
            => prim_app_cb:start_phase(go, normal, [])
            ok

            * 任何時候,都要重視函數(shù)的返回值,通過match確保您的預(yù)期,如果發(fā)生錯誤,那么就大膽的表達(dá)出來。
            posted on 2009-09-24 01:00 暗夜教父 閱讀(624) 評論(0)  編輯 收藏 引用 所屬分類: erlang

            <2009年9月>
            303112345
            6789101112
            13141516171819
            20212223242526
            27282930123
            45678910

            常用鏈接

            留言簿(2)

            隨筆分類

            隨筆檔案

            文章分類

            文章檔案

            搜索

            •  

            最新評論

            閱讀排行榜

            評論排行榜

            久久w5ww成w人免费| 欧美久久综合九色综合| 伊人久久大香线蕉综合网站| 国产精品欧美久久久久天天影视 | 久久亚洲AV成人无码电影| 久久亚洲春色中文字幕久久久| 国产精品久久久久久久久免费 | 久久99精品国产99久久6| 少妇无套内谢久久久久| 欧美精品一区二区精品久久| 精品久久久久久无码人妻蜜桃| 色婷婷综合久久久久中文字幕 | 亚洲欧美日韩精品久久亚洲区 | 久久婷婷国产综合精品 | 狠狠综合久久综合88亚洲| 女人香蕉久久**毛片精品| 久久一日本道色综合久久| 日本加勒比久久精品| 国产精品免费久久久久影院| 久久精品国产久精国产思思| 久久精品国产99国产精品亚洲| 久久国产福利免费| 91超碰碰碰碰久久久久久综合| 精品国产99久久久久久麻豆| 伊人久久大香线蕉综合5g| 麻豆国内精品久久久久久| 日韩AV毛片精品久久久| 久久99国产精品久久久 | 一本色道久久88加勒比—综合| 欧美一区二区三区久久综| 色8激情欧美成人久久综合电| 国内精品久久久久久不卡影院| 国产精品一久久香蕉国产线看 | 国产一区二区三精品久久久无广告| 国产欧美一区二区久久| 国产成人精品久久免费动漫| 久久综合给合久久狠狠狠97色69| 亚洲精品国产美女久久久| 伊人久久精品无码av一区| 日韩精品无码久久久久久| 国产亚洲欧美精品久久久|