erlang 記憶體被大量占用,跟蹤過程

2021-08-31 23:18:13 字數 2327 閱讀 4650

第一步:

檢視程序數目是否正常? erlang:system_info(process_count).

第二步:

檢視節點的記憶體消耗在什麼地方?

> erlang:memory(). [,,

,,,,

,,]顯示記憶體大部分消耗在程序上,由此確定是程序占用了大量記憶體

第三步:

檢視哪些程序占用記憶體最高?

> spawn(fun() -> etop:start([, , , ]) end).

(以輸出text方式啟動etop,其間隔為1秒,輸出行數為20行,按照記憶體排序. 這裡spawn乙個新程序,目的是輸出etop資料時不影響erlang shell 輸入.)

其中」 ,」 表示占用記憶體為 12358050 words(32位系統word size為4,64位系統word size為8, 可以通過erlang:system_info(wordsize) 檢視),在64位系統下將近100m, 太誇張了!

第五步:

手動gc**,希望問題可以解決

>  erlang:garbage_collect(pid(0,12571,0)).

true

再次檢視程序記憶體,發現沒有任何變化!gc沒有**到任何資源,因此消耗的記憶體還在發揮作用,沒有**!

第六步:

不要懷疑系統,首先要懷疑自己的**

認真觀察**,其大致結構如下:

send_msg(socket, pid) ->

tryreceive

->

... ->

...catch

_:_ ->

send_msg(sock, pid)

end.

其目的是迴圈等待資料,然後進行傳送,其使用了try...catch捕獲異常.

這段**有問題麼?

對,這段**的確有問題, 其不是尾遞迴! try...catch會在stack中儲存相應的資訊,異常捕獲需要放置在函式內部,所以send_msg最後呼叫的是try...catch,而不是自身,所以不是尾遞迴!

可以通過**得到驗證:

cat test.erl

-module(test).

-compile([export_all]).

t1() ->

pid = spawn(fun() -> do_t1() end),

send_msg(pid, 100000).

t2() ->

pid = spawn(fun() -> do_t2() end),

send_msg(pid, 100000).

send_msg(_pid, 0) ->

ok;send_msg(pid, n) ->

pid ! <<2:(n)>>,

timer:sleep(200),

send_msg(pid, n-1).

do_t1() ->

erlang:garbage_collect(self()),

result = erlang:process_info(self(), [memory, garbage_collection]),

io:format("~w ~n", [result]),

io:format("backtrace:~w~n~n", [erlang:process_display(self(), backtrace)]),

tryreceive

_ ->

do_t1()

endcatch

_:_ ->

do_t1()

end.

do_t2() ->

erlang:garbage_collect(self()),

result = erlang:process_info(self(), [memory, garbage_collection]),

io:format("~w ~n", [result]),

io:format("backtrace:~w~n~n", [erlang:process_display(self(), backtrace)]),

receive

_ ->

do_t2()

end.

版本1:erlc test.erl && erl -eval "test:t1()"

版本2:erlc test.erl && erl -eval "test:t2()"

你會看到版本1**的呼叫堆疊在不斷增長,記憶體也在增長, 而版本2函式呼叫位址保持不變,記憶體也沒有發生變化!

總結:1,伺服器程式設計中,迴圈一定確保為尾遞迴

2,善於使用otp,如果使用gen_server替換手寫loop,就不會出現這個問題!

Erlang記憶體占用排查流程

使用erlang搭建遊戲伺服器時,運維往往會吐槽cpu占用過高 頻寬太大或者記憶體消耗太快,本文總結一下排查記憶體占用過高的主要思路和流程。erlang system info process count 看是否有大量的異常程序在耗記憶體,之前寫過一篇博文 點我檢視文章 記錄過乙個類似的問題 專案因...

Erlang 程序記憶體占用排查

注 output 指定輸出方式 interval 記憶體資訊重新整理間隔時間 lines 顯示記憶體記錄行數 sort 排序規則 上文指令基於記憶體用量倒排 引數名稱 描述dictionary 程序字典中所有的資料項 registerd name 註冊的名字 status 程序狀態 links 所有...

PHP查詢MySQL大量資料的記憶體占用分析

from 這篇文章主要是從原理,手冊和原始碼分析在php中查詢mysql返回大量結果時,記憶體占用的問題,同時對使用mysql c api也有涉及.昨天,有同事在php討論群裡提到,他做的乙個專案由於mysql查詢返回的結果太多 達10萬條 從而導致php記憶體不夠用.所以,他問,在執行下面的 遍歷...