檢視原始碼 lcnt (工具 v4.1.1)
一個執行時期系統鎖定效能分析工具。
lcnt
模組用於分析 Erlang 執行時期系統中內部執行緒鎖定的效能。啟用 lcnt
後,每次取得鎖定時,執行時期系統中的內部計數器都會更新。計數器會儲存關於取得嘗試次數和取得嘗試期間發生的衝突次數的資訊。計數器還會記錄發生衝突時,鎖定對阻塞執行緒造成的等待時間。
鎖定計數器產生的資料將根據測試的場景,從可平行化的觀點來估計執行時期系統的行為良好程度。這個工具主要開發目的是為了幫助 Erlang 執行時期開發人員解決潛在和通用的瓶頸。
模擬器中的鎖定會根據它們保護的資源類型以及它們在模擬器中的初始化位置來命名,這些是鎖定的「類別」。大多數這些鎖定也會被多次實例化,並給予唯一的識別碼,以增加鎖定的粒度。通常,實例化的鎖定會保護不相交的資源集合,例如 ets 表格、程序或埠。在其他情況下,它會保護特定範圍的資源,例如 pix_lock
,它保護程序映射的索引,並在類別中給予唯一的編號。 lcnt
中的唯一鎖定會透過名稱(類別)和識別碼來參考:{Name, Id}
。
系統中的某些鎖定是靜態的,並保護全域資源,例如 bif_timers
和 run_queue
鎖定。其他鎖定是動態的,並且不一定會長時間存在,例如程序鎖定和 ets 表格鎖定。當刪除鎖定時,可以單獨儲存來自短暫鎖定的統計資料。為了節省記憶體,此行為預設為關閉,但可以透過 lcnt:rt_opt({copy_save, true})
開啟。lcnt:apply/1,2,3
函式可以在分析期間啟用此行為。
另請參閱
摘要
便利函式
等同於 apply(Fun, [])
。
設定鎖定計數器,使用 Args
應用 Fun
,並清理。
建立建立編號為 0 的程序 ID。
等同於 port(node(), Id)
。
建立建立編號為 0 的埠 ID。
內部執行時期鎖定計數器控制器
清除內部計數器。
傳回原始鎖定計數器資料的列表。
傳回目前節點的目前類別遮罩。
設定目前節點的目前鎖定類別遮罩,或擷取遠端節點的目前遮罩。
根據節點 Node
上的 Categories
設定鎖定類別遮罩。
在節點 Node
上設定單個選項。
函式
等同於 clear(node())
。
清除執行時期系統的內部鎖定統計資料。
等同於 collect(node())
。
從執行時期系統收集鎖定統計資料。
等同於 conflicts([])
。
印出內部鎖定及其統計資料的列表。
印出 lcnt
伺服器狀態和關於收集到的鎖定統計資料的一般資訊。
印出特定鎖定的內部鎖定計數器列表。
將先前儲存的資料還原到伺服器。
等同於 locations([])
。
根據原始碼位置印出內部鎖定計數器的列表。
將收集的資料儲存到檔案。
啟動鎖定分析器伺服器。
停止鎖定分析器伺服器。
交換埠和程序的 Name
和 Id
空間的位置。
類型
-type category_atom() :: atom().
-type lock_counter_data() :: term().
-type option() :: {sort, Sort :: sort()} | {reverse, boolean()} | {locations, boolean()} | {thresholds, Thresholds :: [threshold()]} | {print, PrintOptions :: [print() | {print(), non_neg_integer()}]} | {max_locks, MaxLocks :: non_neg_integer() | none} | {combine, boolean()}.
-type print() :: colls | duration | entry | id | name | ratio | time | tries | type.
-type sort() :: colls | entry | id | name | ratio | time | tries | type.
-type threshold() :: {colls, non_neg_integer()} | {time, non_neg_integer()} | {tries, non_neg_integer()}.
便利函式
-spec apply(Fun) -> term() when Fun :: fun().
等同於 apply(Fun, [])
。
設定鎖定計數器,使用 Args
應用 Fun
,並清理。
清除鎖定計數器,然後設定檢測以儲存所有已銷毀的鎖定。設定後,呼叫函式,將 Args
中的元素作為參數傳遞。當函式傳回時,統計資料會立即收集到伺服器。收集後,檢測會恢復為之前的行為。傳回已應用函式的結果。
警告
此函式僅應用於微基準測試;它會在呼叫期間將
copy_save
設定為true
,這可能會很快導致記憶體不足。
建立建立編號為 0 的程序 ID。
等同於 port(node(), Id)
。
建立建立編號為 0 的埠 ID。
內部執行時期鎖定計數器控制器
-spec rt_clear() -> ok.
等同於 rt_clear(node())
。
-spec rt_clear(Node) -> ok when Node :: node().
清除內部計數器。
等同於 lcnt:clear(Node)
。
-spec rt_collect() -> [lock_counter_data()].
等同於 rt_collect(node())
。
-spec rt_collect(Node) -> [lock_counter_data()] when Node :: node().
傳回原始鎖定計數器資料的列表。
-spec rt_mask() -> [category_atom()].
傳回目前節點的目前類別遮罩。
-spec rt_mask(Node) -> [category_atom()] when Node :: node(); (Categories) -> ok | {error, copy_save_enabled} when Categories :: [category_atom()].
設定目前節點的目前鎖定類別遮罩,或擷取遠端節點的目前遮罩。
如果 Arg
是原子,則假定它是一個節點,並且此呼叫會傳回節點 Arg
的目前鎖定類別遮罩。
如果 Arg
是一個列表,則此呼叫等同於 rt_mask(node(), Arg)
。
-spec rt_mask(Node, Categories) -> ok | {error, copy_save_enabled} when Node :: node(), Categories :: [category_atom()].
根據節點 Node
上的 Categories
設定鎖定類別遮罩。
如果啟用 copy_save
選項,此呼叫將會失敗;請參閱 lcnt:rt_opt/2
。
有效的類別如下:
allocator (記憶體分配器)
db
(ETS 表格)debug (除錯)
distribution (分散式)
generic (通用)
io (輸入/輸出)
process (程序)
scheduler (排程器)
此列表隨時可能變更,任何給定鎖定的類別也可能變更。
-spec rt_opt(Node, Option) -> boolean() when Node :: node(), Option :: {Type, Value :: boolean()}, Type :: copy_save | process_locks.
在節點 Node
上設定單個選項。
選項說明
{copy_save, boolean()}
- 保留已銷毀鎖定的統計資料。
預設值:false
警告
啟用此選項時會使用大量記憶體,必須使用
lcnt:rt_clear/0,1
來回收。請注意,它不會區分已銷毀的鎖定和已停用計數的鎖定,因此啟用此選項將會停用鎖定類別遮罩的變更。{process_locks, boolean()}
- 分析程序鎖定,等同於將process
新增至鎖定類別遮罩;請參閱lcnt:rt_mask/2
。
預設值:true
函式
-spec clear() -> ok.
等同於 clear(node())
。
-spec clear(Node) -> ok when Node :: node().
清除執行時期系統的內部鎖定統計資料。
這會清除執行階段系統中的資料,但不會清除伺服器中的資料。所有靜態鎖定的計數器都會歸零,目前存活的所有動態鎖定都會歸零,並且會移除所有已儲存且現在已銷毀的鎖定。它也會重置持續時間計時器。
-spec collect() -> ok.
等同於 collect(node())
。
-spec collect(Node) -> ok when Node :: node().
從執行時期系統收集鎖定統計資料。
如果伺服器尚未啟動,則此函式會啟動伺服器。然後它會將鎖定統計資料填入伺服器。如果伺服器在收集之前有任何鎖定統計資料,則該資料將會遺失。
-spec conflicts() -> ok.
等同於 conflicts([])
。
-spec conflicts(Options) -> ok when Options :: [option()].
印出內部鎖定及其統計資料的列表。
選項說明,請參閱 lcnt:inspect/2
。
-spec information() -> ok.
印出 lcnt
伺服器狀態和關於收集到的鎖定統計資料的一般資訊。
-spec inspect(Lock) -> ok when Lock :: Name | {Name, Id | [Id]}, Name :: atom() | pid() | port(), Id :: atom() | integer() | pid() | port().
等同於 inspect(Lock, [])
。
-spec inspect(Lock, Options) -> ok when Lock :: Name | {Name, Id | [Id]}, Name :: atom() | pid() | port(), Id :: atom() | integer() | pid() | port(), Options :: [option()].
印出特定鎖定的內部鎖定計數器列表。
埠和程序的鎖定 Name
和 Id
可以互換使用 lcnt:swap_pid_keys/0
,這也是為什麼 pid/0
和 port/0
選項可以用在 Name
和 Id
空間的原因。pid 和埠都是具有移除建立的特殊識別碼,可以使用 lcnt:pid/2,3
和 lcnt:port/1,2
重新建立。
選項說明
{combine, boolean()}
- 合併來自鎖定類別不同執行個體的統計資料。
預設值:true
{locations, boolean()}
- 依原始碼檔案和行號列印統計資料。
預設值:false
{max_locks, MaxLocks}
- 列印的最大鎖定數量,若為none
則沒有限制。
預設值:20
{print, PrintOptions}
- 列印選項name
- 已命名的鎖定或已命名的鎖定集合 (類別)。與在 VM 中初始化鎖定時使用的名稱相同。id
- 鎖定集合的內部 ID,不一定唯一。這可能是 ets 表格的表格名稱 (db_tab)、埠的埠 ID、分配器的整數識別碼等等。type
- 鎖定類型:rw_mutex
、mutex
、spinlock
、rw_spinlock
或proclock
。entry
- 與{locations, true}
搭配使用時,此選項會列印鎖定操作的原始碼檔案和行號進入點,以及每個進入點的統計資料。tries
- 此鎖定的取得次數。colls
- 當執行緒嘗試取得此鎖定時的衝突次數。這指的是當 trylock 為 EBUSY、在讀取鎖定 rw_lock 時嘗試寫入、在寫入鎖定 rw_lock 時嘗試讀取、執行緒嘗試鎖定已鎖定的鎖定時。(內部狀態會監視此情況。)ratio
- 衝突次數與嘗試 (取得) 次數之間的比率,以百分比表示。time
- 此鎖定的累積等待時間。這可能會大於實際的實際時間,它是為所有執行緒累積的。Trylock 衝突不會累積時間。duration
- 實際時間的累積等待時間百分比。由於累積時間來自所有執行緒,因此此百分比可能會高於 100%。
預設值:
[name,id,tries,colls,ratio,time,duration]
{reverse, boolean()}
- 反轉排序順序。
預設值:false
{sort, Sort}
- 欄位排序順序。
預設值:time
{thresholds, Thresholds}
- 篩選閾值。任何高於閾值的數值都會通過。
預設值:[{tries, 0}, {colls, 0}, {time, 0}]
-spec load(Filename) -> ok when Filename :: file:filename().
將先前儲存的資料還原到伺服器。
-spec locations() -> ok.
等同於 locations([])
。
-spec locations(Options) -> ok when Options :: [option()].
根據原始碼位置印出內部鎖定計數器的列表。
選項說明,請參閱 lcnt:inspect/2
。
-spec save(Filename) -> ok when Filename :: file:filename().
將收集的資料儲存到檔案。
-spec start() -> {ok, Pid} | {error, {already_started, Pid}} when Pid :: pid().
啟動鎖定分析器伺服器。
伺服器僅作為使用者的媒介,執行由 lcnt:collect/1
收集的資料篩選和列印。
-spec stop() -> ok.
停止鎖定分析器伺服器。
-spec swap_pid_keys() -> ok.
交換埠和程序的 Name
和 Id
空間的位置。