Erlang內(nèi)存

Erlang內(nèi)存占用查詢

Erlang VM大多數(shù)檢測(cè)內(nèi)存的工具都是通過erlang:memory()來實(shí)現(xiàn)的。

1> erlang:memory().
[{total,13772400},
{processes,4390232},
{processes_used,4390112},
{system,9382168},
{atom,194289},
{atom_used,173419},
{binary,979264},
{code,4026603},
{ets,305920}]

首先,所有的返回值都是字節(jié)(bytes)為單位的,它們表示目前被分配的內(nèi)存(Erlang VM實(shí)際使用的內(nèi)存,不是操作系統(tǒng)給Erlang VM分配的內(nèi)存),所以這個(gè)值要比操作系統(tǒng)分配的小很多。
total:當(dāng)前分配給進(jìn)程 processes 和系統(tǒng) system 的內(nèi)存總量
processes:當(dāng)前分配給 Erlang 進(jìn)程的內(nèi)存總量
processes_used:當(dāng)前已被 Erlang 進(jìn)程使用的內(nèi)存總量(進(jìn)程內(nèi)存的一部分)
system:當(dāng)前分配給 Erlang 虛擬機(jī),不過沒有被 Erlang 進(jìn)程占用的內(nèi)存總量。
atom:當(dāng)前分配給原子的內(nèi)存總量(系統(tǒng)進(jìn)程的一部分)
atom_used:當(dāng)前已被 原子使用的內(nèi)存總量(系統(tǒng)進(jìn)程的一部分)
binary:當(dāng)前分配給二進(jìn)制數(shù)據(jù)的內(nèi)存總量(系統(tǒng)進(jìn)程的一部分)
code:當(dāng)前代碼數(shù)據(jù)所占用的內(nèi)存總量(系統(tǒng)進(jìn)程的一部分)
ets:當(dāng)前分配給 ETS 表的內(nèi)存總量(系統(tǒng)進(jìn)程的一部分)

查看進(jìn)程數(shù)目是否正常,是否超過了erlang虛擬機(jī)的最大進(jìn)程數(shù)。

1> erlang:system_info(process_count).

查看占用內(nèi)存最高的進(jìn)程

%% (以輸出text方式啟動(dòng)etop,其間隔為1秒,輸出行數(shù)為20行,按照內(nèi)存排序. 這里spawn一個(gè)新進(jìn)程,目的是輸出etop數(shù)據(jù)時(shí)不影響erlang shell 輸入.)
1> spawn(fun()-> etop:start([{output, text}, {interval, 1}, {lines, 20}, {sort, memory}]) end).

手動(dòng)gc回收內(nèi)存

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

通過erlang:memory()查看節(jié)點(diǎn)內(nèi)存占用總覽,需要通過靜態(tài)和動(dòng)態(tài)兩個(gè)維度對(duì)內(nèi)存進(jìn)行考核:
靜態(tài): 各類內(nèi)存占用比例,是否有某種類的內(nèi)存占用了節(jié)點(diǎn)總內(nèi)存的絕大部分
動(dòng)態(tài): 各類內(nèi)存增長(zhǎng)特性,如增長(zhǎng)速度,或是否長(zhǎng)期增長(zhǎng)而不回收(atom除外)

atom
atom不會(huì)被GC,這意味著我們應(yīng)該對(duì)atom內(nèi)存增長(zhǎng)更加重視而不是忽略。在編寫代碼時(shí),盡量避免動(dòng)態(tài)生成atom,因?yàn)橐坏┠愕妮斎朐床豢煽炕蚴艿焦?特別針對(duì)網(wǎng)絡(luò)消息),atom內(nèi)存增長(zhǎng)可能導(dǎo)致節(jié)點(diǎn)crash。
ets
ets內(nèi)存占用通常是由于表過大,通過ets:i().查看ets表?xiàng)l目數(shù),大小,占用內(nèi)存等。
process
進(jìn)程內(nèi)存占用過高可能有兩方面原因,進(jìn)程數(shù)量過大和進(jìn)程占用內(nèi)存過高。針對(duì)于前者,首先找出那些沒有被鏈接或監(jiān)控的”孤兒進(jìn)程”。
binary
erlang binary大致上分為兩種,heap binary(<=64字節(jié))和refc binary(>64字節(jié)),分別位于進(jìn)程堆和全局堆上,進(jìn)程通過ProBin持有refc binary的引用,當(dāng)refc binary引用計(jì)數(shù)為0時(shí),被GC。

Erlang虛擬機(jī)內(nèi)存布局

Erlang 自己實(shí)現(xiàn)的內(nèi)存分配器, 并非操作系統(tǒng)的內(nèi)存分配器, Erlang 需要調(diào)用操作系統(tǒng)的分配器獲取一大塊內(nèi)存, 并用于 Erlang 系統(tǒng)內(nèi)部的內(nèi)存分配, 來滿足比如創(chuàng)建進(jìn)程, 原子, 二進(jìn)制數(shù)據(jù), 驅(qū)動(dòng)等數(shù)據(jù)結(jié)構(gòu)的內(nèi)存需求。Erlang過程的內(nèi)存布局的三個(gè)重要的點(diǎn):進(jìn)程控制模塊,棧和堆。它和Unix的內(nèi)存布局非常的相像。
進(jìn)程控制模塊:進(jìn)程控制模塊會(huì)保存一些關(guān)于進(jìn)程的信息比如它在進(jìn)程表中的標(biāo)識(shí)符(PID)、當(dāng)前狀態(tài)(運(yùn)行、等待)、它的注冊(cè)名、初始和當(dāng)前調(diào)用,同時(shí)PCB也會(huì)保存一些指向傳入消息的指針,這些傳入消息是存儲(chǔ)在堆中連接表中的。
:它是一個(gè)向下生長(zhǎng)的存儲(chǔ)區(qū),這個(gè)存儲(chǔ)區(qū)保存輸入和輸出參數(shù)、返回地址、本地變量和用于evaluating expressions的臨時(shí)空間。
:它是一個(gè)向上生長(zhǎng)的存儲(chǔ)區(qū),這個(gè)存儲(chǔ)區(qū)保存進(jìn)程郵箱的物理消息,像列表、元組和Binaries這種的復(fù)合項(xiàng)以及比像浮點(diǎn)數(shù)這種一個(gè)機(jī)器字更大的對(duì)象。超過64機(jī)器字的二進(jìn)制項(xiàng)不會(huì)存儲(chǔ)在進(jìn)程私有堆里。他們被稱作Refc Binary (Reference Counted Binary)并被存儲(chǔ)在一個(gè)大的共享堆里,只要有那個(gè)Refc Binary指針的進(jìn)程都可以訪問這個(gè)堆。這個(gè)儲(chǔ)存在進(jìn)程私有堆中的指針叫作ProcBin。
為了結(jié)實(shí)當(dāng)前默認(rèn)Erlang的GC機(jī)制,簡(jiǎn)單的說,它是一個(gè)分代復(fù)制的垃圾回收,獨(dú)立運(yùn)行在每個(gè)Erlang進(jìn)程私有堆的內(nèi)部,而且它也是發(fā)生在全球共享堆中的引用計(jì)數(shù)垃圾回收。

參考
http://erldoc.com/mod/erlang/memory_0.html?search=erlang:&i=156
https://segmentfault.com/a/1190000005064830
https://segmentfault.com/a/1190000003758525
http://wudaijun.com/2015/12/erlang-datastructures/
http://wudaijun.com/2016/12/erlang-memory-debug/

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容