如何衡量 Erlang 垃圾收集器的性能?

How to measure the performance of the Erlang Garbage Collector?

我最近开始使用 Erlang 编程,关于垃圾收集 (GC),我想了解一些事情。据我了解,每个进程的私有堆有分代GC,全局共享堆有引用计数GC。

我想知道的是有没有办法得到:

  1. 收集周期是多少?
  2. 在全局级别或进程级别分配和释放了多少字节?
  3. 私有堆和共享堆的大小是多少?我们可以将其定义为 GC 参数吗?
  4. 收集垃圾需要多长时间?所需时间百分比?
  5. 有没有办法 运行 没有 GC 的程序?

当我 运行 一个 Erlang 程序时,有没有办法通过代码或使用一些命令来获取此类信息?

谢谢。

  1. 要获取单个进程的信息,可以调用erlang:process_info(Pid)。这将产生(从 Erlang 18.0 开始)以下字段:

    > erlang:process_info(self()).
    [{current_function,{erl_eval,do_apply,6}},
     {initial_call,{erlang,apply,2}},
     {status,running},
     {message_queue_len,0},
     {messages,[]},
     {links,[<0.27.0>]},
     {dictionary,[]},
     {trap_exit,false},
     {error_handler,error_handler},
     {priority,normal},
     {group_leader,<0.26.0>},
     {total_heap_size,4184},
     {heap_size,2586},
     {stack_size,24},
     {reductions,3707},
     {garbage_collection,[{min_bin_vheap_size,46422},
                          {min_heap_size,233},
                          {fullsweep_after,65535},
                          {minor_gcs,7}]},
     {suspending,[]}]
    

    进程的收集周期数在 garbage_collection 部分下的字段 minor_gcs 中可用。

  2. 每个进程

    进程的当前堆大小可在上面结果的 heap_size 字段中找到(换言之,32 位 VM 上为 4 个字节,64 位 VM 上为 8 个字节)。进程的总内存消耗可以通过调用 erlang:process_info(Pid, memory) which returns example {memory,34312} 获取上述进程。这包括调用堆栈、堆和内部结构。

    可以使用 erlang:trace/3 跟踪解除分配(和分配)。如果跟踪标志是 garbage_collection,您将收到格式为 {trace, Pid, gc_start, Info}{trace, Pid, gc_end, Info} 的消息。 gc_start 消息的 Info 字段包含 heap_sizeold_heap_size.

    等内容

    每个系统

    系统的顶级统计信息可以通过erlang:memory/0:

    获得
    > erlang:memory().
    [{total,15023008},
     {processes,4215272},
     {processes_used,4215048},
     {system,10807736},
     {atom,202481},
     {atom_used,187597},
     {binary,325816},
     {code,4575293},
     {ets,234816}]
    

    可以通过 erlang:statistics(garbage_collection) 获取垃圾收集统计信息,结果为:

    > statistics(garbage_collection).
    {85,23961,0}
    

    其中(从 Erlang 18.0 开始)第一个字段是 VM 执行的垃圾收集总数,第二个字段是回收的单词总数。

  3. 进程的堆大小在字段 total_heap_size(所有堆碎片和堆栈)和 heap_size(最年轻堆的大小)下可用上面的过程信息。

    它们可以通过 spawn options 控制,特别是 min_heap_size 设置进程的初始堆大小。

    要为所有进程设置它,可以调用erlang:system_flag(min_heap_size, MinHeapSize)

    您还可以通过 +M... 选项控制 Erlang VM 的全局 VM 内存分配。标志描述为 here。但是,这需要对 Erlang VM 及其分配器的内部结构有广泛的了解,使用它们时不应掉以轻心。

  4. 这可以通过答案2中描述的跟踪获得。如果您在跟踪时使用选项timestamp,您将收到一个时间戳,每个跟踪消息可用于计算GC 总时间。

  5. 简答:没有。

    长答案:也许吧。您可以控制初始堆大小(通过 min_heap_size),这将影响第一次进行垃圾收集的时间。您还可以使用 fullsweep_after 选项控制何时执行全面扫描。

可以在效率指南的 Academic and Historical Questions and Processes 部分找到更多信息。

在运行时内省 Erlang 内存使用情况的最实用方法是通过 Recon library, as