查看源代码 instrument (runtime_tools v2.1.1)
用于插桩的分析和实用工具函数
instrument
模块包含用于研究 Erlang 运行时系统中资源使用情况的支持。目前,只能研究内存的分配情况。
注意
由于此模块检查运行时系统的内部细节,因此不同版本之间可能存在很大差异。我们不保证此模块的兼容性。
另请参阅
摘要
类型
-type allocation_summary() :: {HistogramStart :: non_neg_integer(), UnscannedSize :: non_neg_integer(), Allocations :: #{Origin :: allocation_origin() => #{Type :: atom() => block_histogram()}}}.
按其 Origin
和 Type
分组的已分配块大小(包括其头部)的摘要。
Origin
通常是分配块的 NIF 或驱动程序,如果无法确定,则为“system”。
Type
是块所属的分配类别,例如 db_term
、message
或 binary
。这些类别对应于 erl_alloc.types 中的类别。
如果一个或多个载体在不损害系统响应能力的情况下无法完全扫描,则 UnscannedSize
是必须跳过的字节数。
-type block_histogram() :: tuple().
块大小的直方图,其中每个间隔的上限是前一个间隔的两倍。
第一个间隔的上限由返回直方图的函数提供,最后一个间隔没有上限。
例如,下面的直方图在 128-256 字节大小之间有 40 个 (message
) 块,在 256-512 字节之间有 78 个块,在 512-1024 字节之间有 2 个块,在 1-2KB 之间有 2 个块。
> instrument:allocations(#{ histogram_start => 128, histogram_width => 15 }).
{ok, {128, 0, #{ message => {0,40,78,2,2,0,0,0,0,0,0,0,0,0,0}, ... } }}
-type carrier_info_list() :: {HistogramStart :: non_neg_integer(), Carriers :: [{AllocatorType :: atom(), InPool :: boolean(), TotalSize :: non_neg_integer(), UnscannedSize :: non_neg_integer(), Allocations :: [{Type :: atom(), Count :: non_neg_integer(), Size :: non_neg_integer()}], FreeBlocks :: block_histogram()}]}.
AllocatorType
是采用此载体的分配器类型。
InPool
表示载体是否在迁移池中。
TotalSize
是载体的总大小,包括其头部。
Allocations
是载体中已分配块的摘要。请注意,当不同的分配器类型之间共享载体池时,载体可能包含多个不同的块类型(有关更多详细信息,请参阅 erts_alloc
文档)。
FreeBlocks
是载体中空闲块大小的直方图。
如果载体在不损害系统响应能力的情况下无法完全扫描,则 UnscannedSize
是必须跳过的字节数。
函数
-spec allocations() -> {ok, Result} | {error, Reason} when Result :: allocation_summary(), Reason :: not_enabled.
等效于 allocations(#{})
。
-spec allocations(Options) -> {ok, Result} | {error, Reason} when Result :: allocation_summary(), Reason :: not_enabled, Options :: #{scheduler_ids => [non_neg_integer()], allocator_types => [atom()], histogram_start => pos_integer(), histogram_width => pos_integer(), flags => [per_process | per_port | per_mfa]}.
返回系统中所有已标记分配的摘要,可选择按分配器类型和调度器 ID 进行筛选。
默认情况下,只有二进制文件和 NIF 和驱动程序进行的分配会被标记,但这可以通过 +M<S>atags
模拟器选项在每个分配器的基础上进行配置。
如果指定的分配器类型未启用,则调用将失败并返回 {error, not_enabled}
。
可以使用以下选项
allocator_types
- 将要搜索的分配器类型。当启用不同分配器类型之间的载体迁移时,指定特定的分配器类型可能会导致奇怪的结果:您可能会看到意外的类型(例如,在搜索 binary_alloc 时出现进程堆),或者如果块所在的载体已迁移到其他类型的分配器,则块数会少于预期。
默认为所有
alloc_util
分配器。scheduler_ids
- 将要搜索其分配器实例的调度器 ID。调度器 ID 为 0 表示不与任何特定调度器绑定的全局实例。默认为所有调度器和全局实例。histogram_start
- 分配的块大小直方图中第一个间隔的上限。默认为 128。histogram_width
- 分配的块大小直方图中间隔的数量。默认为 18。flags
- 控制如何对输出进行分组,例如,显示每个进程的分配(如果可能),而不仅仅是 NIF/驱动程序基础。默认为[]
。
示例
> instrument:allocations(#{ histogram_start => 128, histogram_width => 15 }).
{ok,{128,0,
#{udp_inet =>
#{driver_event_state => {0,0,0,0,0,0,0,0,0,1,0,0,0,0,0}},
system =>
#{heap => {0,0,0,0,20,4,2,2,2,3,0,1,0,0,1},
db_term => {271,3,1,52,80,1,0,0,0,0,0,0,0,0,0},
code => {0,0,0,5,3,6,11,22,19,20,10,2,1,0,0},
binary => {18,0,0,0,7,0,0,1,0,0,0,0,0,0,0},
message => {0,40,78,2,2,0,0,0,0,0,0,0,0,0,0},
... }
spawn_forker =>
#{driver_select_data_state =>
{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0}},
ram_file_drv => #{drv_binary => {0,0,0,0,0,0,1,0,0,0,0,0,0,0,0}},
prim_file =>
#{process_specific_data => {2,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
nif_trap_export_entry => {0,4,0,0,0,0,0,0,0,0,0,0,0,0,0},
monitor_extended => {0,1,0,0,0,0,0,0,0,0,0,0,0,0,0},
drv_binary => {0,0,0,0,0,0,1,0,3,5,0,0,0,1,0},
binary => {0,4,0,0,0,0,0,0,0,0,0,0,0,0,0}},
prim_buffer =>
#{nif_internal => {0,4,0,0,0,0,0,0,0,0,0,0,0,0,0},
binary => {0,4,0,0,0,0,0,0,0,0,0,0,0,0,0}}}}}
-spec carriers() -> {ok, Result} | {error, Reason} when Result :: carrier_info_list(), Reason :: not_enabled.
等效于 carriers(#{})
。
-spec carriers(Options) -> {ok, Result} | {error, Reason} when Result :: carrier_info_list(), Reason :: not_enabled, Options :: #{scheduler_ids => [non_neg_integer()], allocator_types => [atom()], histogram_start => pos_integer(), histogram_width => pos_integer()}.
返回系统中所有载体的摘要,可选择按分配器类型和调度器 ID 进行筛选。
如果指定的分配器类型未启用,则调用将失败并返回 {error, not_enabled}
。
可以使用以下选项
allocator_types
- 将要搜索的分配器类型。默认为所有alloc_util
分配器。scheduler_ids
- 将要搜索其分配器实例的调度器 ID。调度器 ID 为 0 表示不与任何特定调度器绑定的全局实例。默认为所有调度器和全局实例。histogram_start
- 空闲块大小直方图中第一个间隔的上限。默认为 512。histogram_width
- 空闲块大小直方图中间隔的数量。默认为 14。
示例
> instrument:carriers(#{ histogram_start => 512, histogram_width => 8 }).
{ok,{512,
[{driver_alloc,false,262144,0,
[{driver_alloc,1,32784}],
{0,0,0,0,0,0,0,1}},
{binary_alloc,false,32768,0,
[{binary_alloc,15,4304}],
{3,0,0,0,1,0,0,0}},
{...}|...]}}