|
@ -235,89 +235,91 @@ end. |
|
|
|
|
|
|
|
|
对于长时间运行的会话,eTpf可以旋转跟踪文件。这是一项有助于避免磁盘空间用完的功能,并且不用于保留较小的文件(eTpf可以处理非常大的文件就可以了)。 |
|
|
对于长时间运行的会话,eTpf可以旋转跟踪文件。这是一项有助于避免磁盘空间用完的功能,并且不用于保留较小的文件(eTpf可以处理非常大的文件就可以了)。 |
|
|
|
|
|
|
|
|
lg:trace/3,4可以提供一个映射,而不是将文件名前缀作为第三个参数传递 给。当前有三个选项,包括filename_prefix。其他选项是最大文件大小(以字节为单位)max_size,以及将在文件中每LZ4帧存储的事件数 |
|
|
|
|
|
|
|
|
eTpf:trace/3,4可以提供一个映射,而不是将文件名前缀作为第三个参数传递 给。当前有三个选项,包括filename_prefix。其他选项是最大文件大小(以字节为单位)max_size,以及将在文件中每LZ4帧存储的事件数 |
|
|
events_per_frame。这两个选项使您可以控制文件写入或旋转的频率。 |
|
|
events_per_frame。这两个选项使您可以控制文件写入或旋转的频率。 |
|
|
|
|
|
|
|
|
以下示例将文件大小限制为100MB: |
|
|
以下示例将文件大小限制为100MB: |
|
|
``` |
|
|
``` |
|
|
1> lg:trace('_', lg_file_tracer,#{filename_prefix => "traces.lz4", max_size => 100000000}, #{mode => profile, running =>true}). |
|
|
|
|
|
|
|
|
1> eTpf:trace('_', lg_file_tracer, #{filename_prefix => "traces.lz4", max_size => 100000000}, #{mode => profile, running =>true}). |
|
|
``` |
|
|
``` |
|
|
在测试此功能期间,目前实施的轮换似乎很昂贵,因此您应注意不要设置太低的值。 |
|
|
在测试此功能期间,目前实施的轮换似乎很昂贵,因此您应注意不要设置太低的值。 |
|
|
|
|
|
|
|
|
## Callgrind分析 |
|
|
## Callgrind分析 |
|
|
|
|
|
|
|
|
Looking Glass的主要目的是对Erlang应用程序进行性能分析。这是通过首先将事件跟踪到文件或套接字,然后对其进行处理以提取有用的输出来完成的。 |
|
|
|
|
|
|
|
|
eTpf的主要目的是对Erlang应用程序进行性能分析。这是通过首先将事件跟踪到文件或套接字,然后对其进行处理以提取有用的输出来完成的。 |
|
|
|
|
|
|
|
|
分析工具通常具有几种不同类型的输出。本章是关于callgrind输出的,可以使用qcachegrind/kcachegrind 工具读取。 |
|
|
分析工具通常具有几种不同类型的输出。本章是关于callgrind输出的,可以使用qcachegrind/kcachegrind 工具读取。 |
|
|
|
|
|
|
|
|
快速开始 |
|
|
快速开始 |
|
|
假设您使用概要文件模式和运行标志生成了跟踪文件(如“ 跟踪”一章中所述),则可以使用以下命令生成callgrind.out文件: |
|
|
|
|
|
|
|
|
|
|
|
1 > lg_callgrind:profile_many(“ traces.lz4。* ”,“ callgrind.out ”, |
|
|
|
|
|
#{ running => true })。 |
|
|
|
|
|
|
|
|
假设您使用概要文件模式和运行标志生成了跟踪文件(如Tracer一章中所述),则可以使用以下命令生成callgrind.out文件: |
|
|
|
|
|
``` |
|
|
|
|
|
1> tpCallgrind:profile_many("traces.lz4.*", "callgrind.out", #{running => true}). |
|
|
|
|
|
``` |
|
|
这将为您生成的所有跟踪文件创建一个callgrind.out文件。例如,如果您具有“ traces.lz4.1”和“ traces.lz4.2”,则现在还应该具有“ callgrind.out.1”和“ callgrind.out.2”。 |
|
|
这将为您生成的所有跟踪文件创建一个callgrind.out文件。例如,如果您具有“ traces.lz4.1”和“ traces.lz4.2”,则现在还应该具有“ callgrind.out.1”和“ callgrind.out.2”。 |
|
|
|
|
|
|
|
|
现在,您可以通过用户界面或命令行在cachegrind工具中打开这两个文件: |
|
|
现在,您可以通过用户界面或命令行在cachegrind工具中打开这两个文件: |
|
|
|
|
|
|
|
|
|
|
|
``` |
|
|
$ qcachegrind callgrind.out |
|
|
$ qcachegrind callgrind.out |
|
|
它将自动检测并打开所有与该callgrind.out.*模式匹配的文件。 |
|
|
|
|
|
|
|
|
``` |
|
|
|
|
|
|
|
|
分析一个文件 |
|
|
|
|
|
您可以通过调用函数来分析一个文件 lg_callgrind:profile/2,3。它包含跟踪文件名,输出文件名和一个可选的选项映射: |
|
|
|
|
|
|
|
|
它将自动检测并打开所有与该callgrind.out.*模式匹配的文件。 |
|
|
|
|
|
|
|
|
1 > lg_callgrind:配置文件(“ traces.lz4.1 ”,“ callgrind.out.1 ”)。 |
|
|
|
|
|
|
|
|
Profiling one file |
|
|
|
|
|
您可以通过调用函数来分析一个文件 `tpCallgrind:profile/2,3`。它包含跟踪文件名,输出文件名和一个可选的选项映射: |
|
|
|
|
|
``` |
|
|
|
|
|
1> tpCallgrind:profile("traces.lz4.1", "callgrind.out.1"). |
|
|
|
|
|
``` |
|
|
它还接受以下选项: |
|
|
它还接受以下选项: |
|
|
|
|
|
|
|
|
1 > lg_callgrind:配置文件(“ traces.lz4.1 ”,“ callgrind.out.1 ”, |
|
|
|
|
|
#{ running => true })。 |
|
|
|
|
|
分析许多文件 |
|
|
|
|
|
便利功能可用于一次分析许多文件:lg_callgrind:profile_many/2,3。它以通配符模式作为第一个参数,并以文件名前缀作为第二个参数: |
|
|
|
|
|
|
|
|
|
|
|
1 > lg_callgrind:profile_many(“ traces.lz4。* ”,“ callgrind.out ”)。 |
|
|
|
|
|
如果有两个跟踪文件,这将导致两个“ callgrind.out”文件:“ callgrind.out.1”和“ callgrind.out.2”。 |
|
|
|
|
|
|
|
|
``` |
|
|
|
|
|
1> tpCallgrind:profile("traces.lz4.1", "callgrind.out.1", #{running => true}). |
|
|
|
|
|
``` |
|
|
|
|
|
Profiling many files |
|
|
|
|
|
便利功能可用于一次分析许多文件:`tpCallgrind:profile_many/2,3`, 它以通配符模式作为第一个参数,并以文件名前缀作为第二个参数: |
|
|
|
|
|
``` |
|
|
|
|
|
1> tpCallgrind:profile_many("traces.lz4.*", "callgrind.out"). |
|
|
|
|
|
``` |
|
|
|
|
|
如果有两个跟踪文件,这将导致两个'callgrind.out'文件:'callgrind.out.1'和'callgrind.out.2'。 |
|
|
|
|
|
|
|
|
它还接受以下选项: |
|
|
它还接受以下选项: |
|
|
|
|
|
|
|
|
1 > lg_callgrind:profile_many(“ traces.lz4。* ”,“ callgrind.out ”, |
|
|
|
|
|
#{ running => true })。 |
|
|
|
|
|
运行信息 |
|
|
|
|
|
|
|
|
``` |
|
|
|
|
|
1> tpCallgrind:profile_many("traces.lz4.*", "callgrind.out", #{running => true}). |
|
|
|
|
|
``` |
|
|
|
|
|
Running information |
|
|
当跟踪文件包含运行信息时,这意味着它们是在running启用了标记的情况下创建的,您还需要将running标记传递给事件探查器,以使该信息在'callgrind.out'文件中可用: |
|
|
当跟踪文件包含运行信息时,这意味着它们是在running启用了标记的情况下创建的,您还需要将running标记传递给事件探查器,以使该信息在'callgrind.out'文件中可用: |
|
|
|
|
|
|
|
|
1 > lg_callgrind:profile_many(“ traces.lz4。* ”,“ callgrind.out ”, |
|
|
|
|
|
#{ running => true })。 |
|
|
|
|
|
范围 |
|
|
|
|
|
|
|
|
``` |
|
|
|
|
|
1> tpCallgrind:profile_many("traces.lz4.*", "callgrind.out", #{running => true}). |
|
|
|
|
|
``` |
|
|
|
|
|
Scope |
|
|
默认情况下,跟踪事件的范围是全局的。这意味着cachegrind工具会将所有事件组合在一起,无论它们发生在何处。这对于查看哪些功能总体上占用最多资源很有用。 |
|
|
默认情况下,跟踪事件的范围是全局的。这意味着cachegrind工具会将所有事件组合在一起,无论它们发生在何处。这对于查看哪些功能总体上占用最多资源很有用。 |
|
|
|
|
|
|
|
|
其他时间,您可能想查看哪些进程占用最多的资源。为此,您需要指示Looking Glass在生成“ callgrind.out”文件时保留过程信息。使用以下scope选项完成此操作: |
|
|
|
|
|
|
|
|
|
|
|
1 > lg_callgrind:profile_many(“ traces.lz4。* ”,“ callgrind.out ”, |
|
|
|
|
|
#{ scope => per_process })。 |
|
|
|
|
|
|
|
|
其他时间,您可能想查看哪些进程占用最多的资源。为此,您需要指示eTpf在生成“ callgrind.out”文件时保留过程信息。使用以下scope选项完成此操作: |
|
|
|
|
|
``` |
|
|
|
|
|
1> lg_callgrind:profile_many("traces.lz4.*", "callgrind.out", #{scope => per_process}). |
|
|
|
|
|
``` |
|
|
使用cachegrind工具 |
|
|
使用cachegrind工具 |
|
|
当将cachegrind工具与Looking Glass生成的输出一起使用时,需要注意一些陷阱。 |
|
|
当将cachegrind工具与Looking Glass生成的输出一起使用时,需要注意一些陷阱。 |
|
|
|
|
|
|
|
|
cachegrind工具在构建时就考虑了命令性代码。递归处理得不太好。这意味着调用函数的次数可能并不总是正确的,尤其是对于调用自身的函数而言。例如,在查看调用图时,您可以看到此问题的示例。 |
|
|
cachegrind工具在构建时就考虑了命令性代码。递归处理得不太好。这意味着调用函数的次数可能并不总是正确的,尤其是对于调用自身的函数而言。例如,在查看调用图时,您可以看到此问题的示例。 |
|
|
|
|
|
|
|
|
当使用该scope ⇒ per_process选项时,Looking Glass使用ELF对象字段来存储过程的pid 。这使您可以通过使用“分组”功能并选择“ ELF对象”来单独调查过程。然后,您可以查看哪些进程占用最多的资源,并查看这些进程中的函数调用。 |
|
|
|
|
|
|
|
|
当使用该`scope => per_process`选项时,Looking Glass使用ELF对象字段来存储过程的pid 。这使您可以通过使用'grouping'功能并选择'ELF Object'来单独调查过程。 |
|
|
|
|
|
然后,您可以查看哪些进程占用最多的资源,并查看这些进程中的函数调用。 |
|
|
|
|
|
|
|
|
使用运行标志时,将生成以下事件类型: |
|
|
使用运行标志时,将生成以下事件类型: |
|
|
|
|
|
* Total time in microseconds |
|
|
|
|
|
* Active time in microseconds |
|
|
|
|
|
* Wait time in microseconds (scheduled out) |
|
|
|
|
|
* Number of times the process was scheduled out |
|
|
|
|
|
|
|
|
总时间(以微秒为单位) |
|
|
|
|
|
|
|
|
|
|
|
激活时间(以微秒为单位) |
|
|
|
|
|
|
|
|
|
|
|
等待时间(以微秒为单位) |
|
|
|
|
|
|
|
|
|
|
|
计划处理的次数 |
|
|
|
|
|
|
|
|
|
|
|
以下公式是正确的:Total = Active + Wait。 |
|
|
|
|
|
|
|
|
以下公式是正确的:`Total = Active + Wait`. |
|
|
|
|
|
|
|
|
等待时间是指计划该流程(即它未运行)所花费的时间。这发生在许多不同的地方,例如接收子句或减少计数达到零时。 |
|
|
|
|
|
|
|
|
等待时间是指计划该流程(即它未运行)所花费的时间。这发生在许多不同的地方,like receive clauses or when the reduction count reached zero. |
|
|
|
|
|
|
|
|
目前,计划的时间安排可能不准确。另一个可能不准确的部分是花费在执行端口操作上的时间,该时间可能在进程主要等待时显示为活动时间。两者都将在未来得到改进。 |
|
|
|
|
|
|
|
|
目前,process was scheduled out 次数统计可能不准确。另一个可能不准确的部分是花费在执行端口操作上的时间,该时间可能在进程主要等待时显示为活动时间。两者都将在未来得到改进。 |
|
|
|
|
|
|
|
|
虽然Looking Glass提供了有关各种调用的行号信息,但它无法识别此调用过程中涉及的函数子句。这意味着当在cachegrind工具中查看源代码时,具有很多子句的函数的调用信息将聚集在同一行号上。这对大多数标准行为(包括handle_event 来自)具有重要影响gen_statem。但是,您可以对代码进行结构化,以使子句繁重的函数仅分派给其他函数,从而在cachegrind工具中获得更好的视图。 |
|
|
|
|
|
|
|
|
虽然eTpf提供了有关各种调用的行号信息,但它无法识别此调用过程中涉及的函数子句。 |
|
|
|
|
|
这意味着当在cachegrind工具中查看源代码时,具有很多子句的函数的调用信息将聚集在同一行号上。 |
|
|
|
|
|
这对大多数标准行为(包括handle_event 来自)具有重要影响gen_statem。但是,您可以对代码进行结构化,以使子句繁重的函数仅分派给其他函数,从而在cachegrind工具中获得更好的视图。 |
|
|
|
|
|
|
|
|
Looking Glass目前无法找到列表理解和乐趣的行号。他们将始终指向第1行。 |
|
|
|
|
|
|
|
|
eTpf目前无法找到列表理解和匿名函数的行号。他们将始终指向第1行。 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
## Flame graph profiling |
|
|
## Flame graph profiling |
|
|