Simpleperf 介绍

Outline

  • What is simpleperf

  • How simpleperf works

  • Simpleperf commands

simpleperf 是什么?

  • 替代 Linux 的 perf 工具: simpleperf 是 Android 系统中 linux/tools/perf 的替代品。perf 是 Linux 中常用的性能分析工具,而 simpleperf 则是为 Android 系统优化的版本,提供类似的功能。
  • CPU 分析工具,利用 Linux 内核和 PMU 硬件支持: simpleperf 是一个 CPU 分析器,它依赖于 Linux 内核的支持和 PMU(Performance Monitoring Unit,性能监控单元)硬件的支持。PMU 是一种存在于现代 CPU 中的硬件单元,用于收集性能事件(如 CPU 周期、缓存未命中等)。
  • 源代码位置: simpleperf 的源代码可以在 Google 的 Android 开源项目(AOSP) 中找到。这意味着 simpleperf 是开源的,开发者可以查看、修改和编译它的源代码。
  • 文档位置: 与 simpleperf 相关的文档可以在 这个链接 中找到。文档中通常会有详细的使用指南、配置说明、以及如何解读 simpleperf 的输出结果。
  • 预编译的版本发布位置: 已编译好的 simpleperf 二进制文件可以在 这里 下载。这对于开发者和用户来说很方便,因为他们不需要自己编译源代码,可以直接下载并使用预编译的版本。

Simpleperf 的工作原理

simpleperf 是一个为 Android 设计的强大 CPU 分析工具,它利用 Linux 内核的功能和硬件支持,能够深入分析性能。以下是 simpleperf 的工作原理:

1. 性能事件监控

  • 硬件和软件事件simpleperf 可以监控多种性能事件,包括硬件事件(如 CPU 周期、缓存命中/未命中)和软件事件(如页面错误、上下文切换)。硬件事件通过现代 CPU 中的性能监控单元(PMU)来跟踪,而软件事件则通过内核设施来监控。
  • 事件收集:当运行 simpleperf 时,它会指示 CPU 开始收集指定事件的数据。这些事件可以是硬件计数器或软件信号。收集的数据包括执行的指令数、缓存未命中次数、分支预测失败等指标。

2. 采样

  • 定期采样simpleperf 通过定期采样 CPU 的状态来工作。与记录每个事件(这会导致性能开销过大)不同,simpleperf 在固定的时间间隔内采集系统状态,捕获这些时刻的关键指标。
  • 调用图记录:使用 -g 选项时,simpleperf 不仅记录事件数据,还会在每次采样时捕获调用栈。这有助于理解特定事件(如缓存未命中)发生时,哪些函数正在执行。

3. 记录数据

  • 数据收集:采样到的数据会被收集并存储在一个配置文件中。该文件包含哪些事件发生了、它们在代码中的发生位置(通过调用栈信息)以及它们发生的频率等信息。
  • 多种事件类型simpleperf 允许同时监控多种事件类型,这有助于识别涉及多个瓶颈类型的复杂性能问题。

4. 分析

  • 后期处理:数据收集完成后,可以使用 simpleperf 或其他工具进行分析。simpleperf 提供了 reportreport-htmlannotate 等命令来可视化和理解数据。
  • 识别热点:分析阶段通常涉及识别代码中的 “热点”——即 CPU 大部分时间花费的地方。这些热点通常是优化性能的首要目标。
  • 与源代码的关联simpleperf 可以将收集到的事件数据映射回源代码,使开发人员能够确切地看到哪些代码行导致了性能问题。

5. 实时分析

  • 实时记录simpleperf 也可以用于实时监控和分析正在运行的应用程序。这在开发和调试场景中尤为有用,因为理解实时应用程序的性能特征对优化至关重要。

6. 跨平台使用

  • Android 及其他平台:虽然 simpleperf 为 Android 优化,但它足够灵活,可以在其他基于 Linux 的系统上使用。它可以在各种设备上运行,从智能手机到功能更强大的开发机器,使其成为开发人员工具包中的一个多功能工具。

TODO这里补充一张图

ARM PMU (性能监控单元)

ARM 的性能监控单元(PMU)是现代 ARM 处理器中的一个关键组件,允许开发者监控和分析各种硬件性能指标。以下是对你提供的文档内容的详细解释:

1. ARM 手册中的描述

  • 参考文档: ARM PMU 的功能和使用在 ARM 手册中有详细描述,特别是在 D7 章节性能监控扩展(The Performance Monitors Extension)。这是开发者获取 PMU 详细技术信息和使用指导的重要资源。

2. PMU 计数器

  • 每个 CPU 核心有多个 PMU 计数器: ARM 处理器的每个 CPU 核心都有多个 PMU 计数器,这些计数器用于监控特定的 PMU 事件。
  • 32 位计数器: 每个 PMU 计数器是 32 位的,即它们可以记录的最大值是 2^32 - 1(约 42 亿)。每个计数器可以同时监控一个 PMU 事件。
  • 事件发生时计数器递增: 当被监控的事件发生时,计数器的值会增加 1。
  • 计数器溢出和中断: 如果一个计数器的值超过了其 32 位的容量(即发生溢出),它可以触发一个中断。这通常用于捕捉高频率的事件或者监控运行时间较长的进程。

3. PMU 事件

  • 常见的 PMU 事件

    : PMU 事件是硬件层面发生的特定活动。例如:

    • CPU_CYCLES: CPU 周期数,表示 CPU 核心经过的时钟周期数。
    • BR_PRED: 可预测分支,表示处理器成功预测到的分支。
    • L1D_CACHE: 一级数据缓存访问次数。
  • ARM 提供了常见事件的解释: ARM 手册列出了常见的 PMU 事件,并解释了这些事件的意义和使用方式。

  • 事件的组合使用: 通过组合使用不同的 PMU 事件,开发者可以获得间接的信息。例如,缓存未命中率 可以通过 cache refill count / cache_access_count 计算得出。

  • 新架构中的 PMU 事件: 在更新的 ARM 架构中,支持的 PMU 事件种类在不断增加,这为开发者提供了更丰富的性能分析工具。

Simpleperf 命令文档

这段文档简要介绍了 simpleperf 工具及其主要命令的功能。以下是文档的翻译和解释:

1. Simpleperf 简介

  • 可执行文件simpleperf 是一个在设备上运行的可执行文件,通常存放在 /system/bin 目录中。这意味着它已经预先安装在 Android 设备上,用户可以直接在设备上使用它来进行性能分析。
  • 子命令划分simpleperf 将其功能分为多个子命令,每个子命令执行特定的性能分析任务。通过这种方式,simpleperf 提供了灵活的使用方式,可以根据需求执行不同的操作。

2. 主要子命令

  • list 命令
    • 功能:列出设备上可用的性能事件。使用这个命令可以查看当前设备支持监控哪些性能事件。
  • stat 命令
    • 功能:监控指定的线程,并打印出性能事件计数器的值。这个命令可以用来实时监控应用程序或线程的性能表现。
  • record 命令
    • 功能:监控指定的线程,并生成包含采样数据的性能分析数据文件。这个命令通常用于在运行期间收集性能数据,供后续分析使用。
  • report 命令
    • 功能:对由 record 命令生成的性能分析数据文件进行分析,并生成报告。这个报告可以帮助开发者了解应用程序的性能瓶颈和热点。

3. Simpleperf 提供的 Python 脚本

  • Python 脚本

    :simpleperf

    还提供了一些在主机(开发者的电脑)上运行的 Python 脚本,这些脚本的主要作用包括:

    • 辅助记录:帮助更方便地进行数据记录操作。
    • 辅助报告:帮助生成和分析性能报告,使开发者能够更直观地理解性能数据。

simpleperf list 命令

功能:

  • 列出可用的性能事件simpleperf list 命令用于显示设备上可用的硬件和软件性能事件。这些事件是 simpleperf 可以监控的,帮助开发者了解系统在运行应用程序时的性能表现。

硬件事件列表:

这些事件与硬件相关,通常直接由 CPU 或其他硬件组件生成。常见的硬件事件包括:

  • branch-misses(分支预测失败次数):记录 CPU 分支预测失败的次数。
  • bus-cycles(总线周期):记录 CPU 在总线上花费的周期数,通常用于衡量内存访问或 I/O 操作。
  • cache-misses(缓存未命中次数):记录数据请求未能在缓存中找到的次数。
  • cache-references(缓存访问次数):记录缓存访问的总次数(包括命中和未命中)。
  • cpu-cycles(CPU 周期数):记录 CPU 使用的时钟周期数。
  • instructions(指令数):记录 CPU 执行的指令总数。
  • stalled-cycles-backend(后端停顿周期数):记录 CPU 流水线后端由于数据依赖或资源限制而停顿的周期数。
  • stalled-cycles-frontend(前端停顿周期数):记录 CPU 流水线前端由于指令未准备好而停顿的周期数。

软件事件列表:

这些事件与操作系统的行为或软件环境相关。常见的软件事件包括:

  • alignment-faults(对齐错误次数):记录由于内存访问未对齐导致的错误次数。
  • context-switches(上下文切换次数):记录 CPU 从一个进程或线程切换到另一个的次数。
  • cpu-clock(CPU 时间):记录 CPU 所使用的时钟时间量,用于测量进程或线程的 CPU 使用情况。

更加详细的讲解

simpleperf list 命令的功能

simpleperf 是一个强大的性能分析工具,专门用于 Android 平台的性能监控。list 命令是 simpleperf 的一个子命令,用于列出当前设备上支持的所有性能事件。这些事件分为两类:硬件事件和软件事件。每种事件都提供了关于系统性能的特定信息,有助于开发者优化应用程序。

硬件事件(Hardware Events)

硬件事件通常由 CPU 或其他硬件组件生成,直接反映了处理器的运行状况和效率。以下是列出的硬件事件的详细解释:

  1. branch-misses(分支预测失败次数)
    • 描述:记录 CPU 分支预测失败的次数。当处理器错误地预测了程序将要执行的路径时,就会发生分支预测失败。这会导致流水线清空,从而增加延迟。
    • 用途:用于分析代码中的分支逻辑是否复杂或难以预测,进而优化代码结构以提高预测命中率。
  2. bus-cycles(总线周期)
    • 描述:记录 CPU 在总线上花费的周期数。总线周期指的是 CPU 访问内存或外设的时间。
    • 用途:用于衡量系统的内存或 I/O 访问性能,帮助识别内存瓶颈或总线争用问题。
  3. cache-misses(缓存未命中次数)
    • 描述:记录 CPU 请求的数据未能在缓存中找到的次数。当发生缓存未命中时,数据必须从较慢的主存中获取,从而增加了访问延迟。
    • 用途:用于评估缓存的有效性,帮助开发者优化缓存利用率,减少缓存未命中率。
  4. cache-references(缓存访问次数)
    • 描述:记录缓存访问的总次数,包括命中和未命中。这表明处理器尝试从缓存中获取数据的频率。
    • 用途:通过与 cache-misses 结合使用,开发者可以计算缓存命中率,并分析程序的内存访问模式。
  5. cpu-cycles(CPU 周期数)
    • 描述:记录 CPU 处理指令时的时钟周期数。这个事件提供了 CPU 使用的基本衡量标准。
    • 用途:用于分析 CPU 的整体性能,了解程序的执行时间和 CPU 资源的消耗情况。
  6. instructions(指令数)
    • 描述:记录 CPU 执行的指令总数。这是衡量程序执行量的直接指标。
    • 用途:与 cpu-cycles 结合,可以计算每个周期执行的指令数(IPC),用于评估 CPU 的效率。
  7. stalled-cycles-backend(后端停顿周期数)
    • 描述:记录 CPU 流水线后端由于数据依赖或资源限制而停顿的周期数。当流水线无法推进时,这些周期会被记录下来。
    • 用途:帮助识别数据依赖和资源争用问题,指导开发者在程序优化时减少后端停顿。
  8. stalled-cycles-frontend(前端停顿周期数)
    • 描述:记录 CPU 流水线前端由于指令未准备好或分支预测失败而停顿的周期数。
    • 用途:用于分析指令获取阶段的问题,例如缓存未命中或指令解码瓶颈。

软件事件(Software Events)

软件事件通常由操作系统或软件层生成,反映系统运行时的操作情况。以下是列出的软件事件的详细解释:

  1. alignment-faults(对齐错误次数)
    • 描述:记录由于内存访问未对齐导致的错误次数。在某些架构中,内存访问要求数据在特定地址对齐,否则会导致性能下降或故障。
    • 用途:帮助开发者发现和修复未对齐的内存访问,提高内存访问效率。
  2. context-switches(上下文切换次数)
    • 描述:记录 CPU 从一个进程或线程切换到另一个的次数。上下文切换是多任务操作系统中常见的操作,但频繁的切换会带来性能开销。
    • 用途:用于分析多线程应用程序的性能,优化上下文切换的频率,以减少系统开销。
  3. cpu-clock(CPU 时间)
    • 描述:记录 CPU 的时钟时间量,用于测量进程或线程占用 CPU 的时间。
    • 用途:用于分析进程或线程的 CPU 使用情况,帮助优化计算密集型任务的性能。

simpleperf stat 命令的选项说明

simpleperf stat 是一个用于收集和显示正在运行的命令或进程的性能计数器信息的命令。它可以实时监控多个性能事件,帮助开发者了解应用程序的运行状况。以下是 simpleperf stat 命令及其选项的详细解释:

命令语法

bash
复制代码
Usage: simpleperf stat [options] [command [command-args]]
  • 功能simpleperf stat 命令用于收集正在运行的 [command] 的性能计数器信息。你可以直接监控一个正在运行的命令,或者通过进程 ID(PID)或线程 ID(TID)来监控特定的进程或线程。

选项说明

  • -p pid1,pid2,...
    • 描述:监控指定进程的性能事件。
    • 用法:通过逗号分隔的方式指定一个或多个进程 ID(PID)。这个选项适用于你想要监控已经在运行的特定进程。
    • 示例-p 1234,5678 监控 PID 为 1234 和 5678 的进程。
  • -t tid1,tid2,...
    • 描述:监控指定线程的性能事件。
    • 用法:通过逗号分隔的方式指定一个或多个线程 ID(TID)。这个选项适用于你想要精确监控某些特定线程的情况。
    • 示例-t 2345,6789 监控 TID 为 2345 和 6789 的线程。
  • -a
    • 描述:收集系统范围内的信息。
    • 用法:使用此选项时,simpleperf 将监控整个系统中的性能事件,而不仅仅是特定的进程或线程。
    • 示例-a 监控整个系统的性能数据。
  • --cpu cpu_item1,cpu_item2,...
    • 描述:仅在选定的 CPU 上收集信息。
    • 用法:通过逗号分隔的方式指定一个或多个 CPU 项(CPU 核心)。这个选项适用于只想监控特定 CPU 核心上运行的进程或线程的情况。
    • 示例--cpu 0,1 仅在 CPU 0 和 CPU 1 上收集信息。
  • -e event1[:modifier1],event2[:modifier2],...
    • 描述:选择要统计的事件列表。
    • 用法:你可以指定一个或多个性能事件,通过逗号分隔。每个事件后可以跟随一个可选的修饰符,用于更具体地控制事件的监控方式。
    • 示例-e cpu-cycles,cache-misses 统计 CPU 周期数和缓存未命中次数。
  • --duration time_in_sec
    • 描述:监控指定时间长度(以秒为单位)。
    • 用法:设置 simpleperf stat 运行的持续时间。它将在指定的时间后停止监控。
    • 示例--duration 10 监控 10 秒钟的性能数据。

simpleperf stat 命令示例解释

这个示例展示了如何使用 simpleperf stat 命令来监控系统范围内的缓存引用和缓存未命中事件,并在指定的持续时间内收集这些事件的统计信息。

命令分析

css
复制代码
$ simpleperf stat -e cache-references,cache-misses -a --duration 1
  • -e cache-references,cache-misses

    :

    • 指定要监控的两个性能事件:cache-references(缓存访问次数)和 cache-misses(缓存未命中次数)。
  • -a

    :

    • 进行系统范围内的监控,而不仅仅是特定的进程或线程。
  • --duration 1

    :

    • 设置监控的持续时间为 1 秒钟。命令将在 1 秒钟后自动结束。

输出解释

yaml复制代码Performance counter statistics:
#
count event_name
# count / runtime, runtime / enabled_time
774,728,087 cache-references # 96.513 M/sec (100%)
31,985,983 cache-misses # 4.128672% miss rate (100%)
Total test time: 1.001893 seconds.
  • Performance counter statistics:
    • 这个标题表示接下来是性能计数器的统计数据。
  • 774,728,087 cache-references:
    • 在 1 秒的测试时间内,共记录了 774,728,087 次缓存访问事件。
    • # 96.513 M/sec:每秒大约有 96.513 百万次缓存访问事件发生。
    • (100%):表示在整个测试时间内,监控是完全启用的(没有丢失数据)。
  • 31,985,983 cache-misses:
    • 在同一时间段内,共记录了 31,985,983 次缓存未命中事件。
    • # 4.128672% miss rate:缓存未命中率为 4.128672%。这意味着每 100 次缓存访问中,大约有 4.13 次是未命中,需要从更慢的主存中读取数据。
    • (100%):表示监控期间数据完全启用,没有丢失。
  • Total test time: 1.001893 seconds:
    • 表示测试持续了大约 1.001893 秒。这个时间包括了命令运行和性能数据收集的全部时间。

simpleperf record 命令的选项说明

simpleperf record 是一个用于记录指定命令或进程的采样信息的命令。它通过采集性能事件的样本数据,生成详细的性能分析报告。以下是 simpleperf record 命令的选项的详细解释:

命令语法

bash
复制代码
Usage: simpleperf record [options] [--] [command [command-args]]
  • 功能simpleperf record 命令用于对正在运行的 [command] 进行采样,记录相关的性能事件信息。采样数据通常用于生成性能分析报告。

选项说明

  • -p pid1,pid2,...
    • 描述:记录指定进程的性能事件。
    • 用法:通过逗号分隔的方式指定一个或多个进程 ID(PID)。这个选项适用于监控和记录已经在运行的特定进程的性能事件。
    • 示例-p 1234,5678 记录 PID 为 1234 和 5678 的进程。
  • -t tid1,tid2,...
    • 描述:记录指定线程的性能事件。
    • 用法:通过逗号分隔的方式指定一个或多个线程 ID(TID)。这个选项适用于精确监控和记录某些特定线程的情况。
    • 示例-t 2345,6789 记录 TID 为 2345 和 6789 的线程。
  • -a
    • 描述:进行系统范围内的数据采集。
    • 用法:使用此选项时,simpleperf 将记录整个系统中的性能事件,而不仅仅是特定的进程或线程。
    • 示例-a 记录整个系统的性能数据。
  • --cpu cpu_item1,cpu_item2,...
    • 描述:仅在选定的 CPU 上收集信息。
    • 用法:通过逗号分隔的方式指定一个或多个 CPU 项(CPU 核心)。这个选项适用于只想监控特定 CPU 核心上运行的进程或线程的情况。
    • 示例--cpu 0,1 仅在 CPU 0 和 CPU 1 上收集信息。
  • -e event1[:modifier1],event2[:modifier2],...
    • 描述:选择要统计的事件列表。
    • 用法:你可以指定一个或多个性能事件,通过逗号分隔。每个事件后可以跟随一个可选的修饰符,用于更具体地控制事件的采集方式。
    • 示例-e cpu-cycles,cache-misses 记录 CPU 周期数和缓存未命中次数。
  • -f freq
    • 描述:设置事件采样频率。表示每秒最多记录 [freq] 次样本。
    • 用法:这个选项控制采样的频率。较高的频率会生成更多的数据,但也会增加系统开销。
    • 示例-f 1000 每秒最多记录 1000 个样本。
  • --duration time_in_sec
    • 描述:监控指定时间长度(以秒为单位)。
    • 用法:设置 simpleperf record 运行的持续时间。它将在指定的时间后自动结束采样。
    • 示例--duration 10 记录 10 秒钟的性能数据。
  • -o record_file_name
    • 描述:设置记录文件的名称,默认文件名为 perf.data
    • 用法:指定采样数据保存的文件名。如果不指定,数据会保存到默认文件 perf.data 中。
    • 示例-o myrecord.data 将采样数据保存为 myrecord.data
  • --call-graph fp | dwarf[,<dump_stack_size>]
    • 描述:启用调用图记录。
    • 用法:使用 fpdwarf 来启用调用栈记录。fp 使用帧指针来记录调用栈,而 dwarf 使用 DWARF 调试信息。可以选择性地指定堆栈大小(以字节为单位)。
    • 示例--call-graph dwarf 启用 DWARF 格式的调用栈记录。
  • -g
    • 描述:启用调用图记录,等同于 --call-graph dwarf
    • 用法:这个选项是 --call-graph dwarf 的快捷方式,启用基于 DWARF 的调用栈记录。
    • 示例-g 启用 DWARF 格式的调用栈记录。

simpleperf record 命令示例解释

这个示例展示了如何使用 simpleperf record 命令来记录性能数据,并在命令执行期间启用调用栈的记录。以下是对该命令的逐步解释:

命令分析

shell
复制代码
$ simpleperf record -g sleep 1
  • record: 表示使用 simpleperf 的记录功能,该命令将对指定的进程或线程进行采样,并生成性能分析数据。
  • -g: 启用调用图记录,相当于 --call-graph dwarf,表示在记录性能事件时,同时记录调用栈信息(基于 DWARF 格式)。这有助于了解事件发生时,程序的执行路径和上下文。
  • sleep 1: 这是一个简单的命令,它让系统休眠 1 秒钟。simpleperf 将在这 1 秒钟内对 sleep 命令的执行进行采样。

输出解释

css
复制代码
simpleperf I cmd_record.cpp:696] Recorded for 1.01908 seconds. Start post processing.
  • Recorded for 1.01908 seconds.:表示 simpleperf 实际上记录了大约 1.01908 秒的性能数据。这个时间包括了 sleep 1 命令的运行时间和系统的一些微小开销。
  • Start post processing.:表示采样数据的记录部分已经完成,simpleperf 正在开始对采集到的数据进行后处理。这通常涉及整理、优化采样数据,以便后续使用 report 命令分析。
css
复制代码
simpleperf I cmd_record.cpp:771] Samples recorded: 56. Samples lost: 0.
  • Samples recorded: 56.:表示在这 1 秒的时间内,共记录了 56 个样本。这些样本代表了 sleep 命令在执行期间的性能事件数据。
  • Samples lost: 0.:表示在记录过程中没有丢失样本。这意味着所有采集到的数据都被成功记录,没有因系统过载或其他因素导致的数据丢失。

simpleperf record 命令的样本格式解释

simpleperf record 命令生成的性能分析数据文件包含了多个样本(samples),每个样本记录了在采样时刻发生的关键性能信息。以下是样本中可能包含的信息及其解释:

样本中包含的信息

  • time - 时间戳(CLOCK_MONOTONIC):
    • 描述:表示样本的时间戳,使用的是 CLOCK_MONOTONIC 时钟。这是一个从系统启动后开始计时的单调递增时钟,确保每个样本的时间戳是唯一且递增的。
    • 用途:帮助确定每个样本采集的精确时间,用于分析事件发生的时序和间隔。
  • pid, tid - 进程 ID 和线程 ID:
    • 描述pid 是样本对应的进程 ID,而 tid 是样本对应的线程 ID。如果线程是主线程,则 pidtid 会相同。
    • 用途:用于识别样本数据来自哪个进程和线程,帮助在多线程或多进程环境中进行细粒度的性能分析。
  • cpu - CPU:
    • 描述:记录样本被捕获时执行线程所在的 CPU 核心编号。
    • 用途:用于分析工作负载在多核处理器上的分布情况,识别可能的 CPU 亲和性问题或负载不均衡。
  • period - 周期:
    • 描述:表示自上次采样以来发生的事件数量。simpleperf 并不会每次事件发生时都进行记录,而是基于采样率在一定间隔采样,所以 period 显示了这些间隔期间累计的事件数。
    • 用途:帮助理解特定时间段内事件的密集度,用于统计分析和性能瓶颈的识别。
  • ips[] - 调用栈(基于帧指针的调用栈):
    • 描述:这是一个调用栈(Callstack)数组,表示从当前采样点回溯的函数调用链。ips 基于帧指针(frame pointer)记录的调用栈信息。
    • 用途:用于分析程序执行路径,帮助确定性能热点,以及理解复杂调用链中性能问题的来源。
  • regs[] - 用户空间寄存器值:
    • 描述:记录用户空间的寄存器值(如通用寄存器的值)在采样时刻的状态。
    • 用途:用于低级别的性能分析或调试,帮助理解在特定采样点时,CPU 寄存器的状态。
  • stack[] - 用户栈数据(最大 64KB):
    • 描述:记录了用户空间栈中的数据,最多可记录 64KB 的栈数据。
    • 用途:用于更详细的堆栈分析,尤其是在需要了解深层函数调用中的具体数据时有用。

simpleperf report 命令示例解释

simpleperf report 命令用于分析和展示由 simpleperf record 命令生成的性能分析数据。该命令将采集到的数据进行解析,并以人类可读的形式输出,帮助开发者理解性能瓶颈和热点。以下是你提供的示例输出的详细解释:

命令分析

ruby
复制代码
$ simpleperf report
  • 功能:此命令用于报告先前通过 simpleperf record 收集的性能分析数据。报告中包含了关于 CPU 使用情况、采样数据和热点函数的信息。

输出解释

bash
复制代码
Cmdline: /system/bin/simpleperf record -g sleep 1
  • 描述:显示用于生成分析数据的命令行参数。这表明数据是通过命令 /system/bin/simpleperf record -g sleep 1 生成的,即记录了 sleep 命令执行 1 秒期间的性能数据,并启用了调用图记录(-g)。
makefile
复制代码
Arch: arm64
  • 描述:显示目标系统的架构。在这个例子中,架构是 ARM64(通常指 64 位的 ARM 处理器)。
vbnet复制代码Event: cpu-cycles (type 0, config 0)
Samples: 56
Event count: 13885436
  • Event:表示正在报告的性能事件是 cpu-cycles,即 CPU 周期数。这是一个常见的硬件性能事件,用于测量 CPU 的时钟周期数。
  • Samples:表示在记录期间收集到的样本数量是 56 个。这些样本代表了 simpleperf 采集的数据点。
  • Event count:表示记录的事件总数是 13885436,表示在 sleep 运行期间,总共消耗了 13885436 个 CPU 周期。
vbnet
复制代码
Overhead Command Pid Tid Shared Object
  • 描述

    :这个标题表示以下数据列的含义:

    • Overhead:表示该函数或操作占总 CPU 周期的百分比,数值越高,表示该部分消耗了更多的 CPU 资源。
    • Command:表示样本来自哪个命令(在这个例子中是 sleep)。
    • PidTid:分别表示进程 ID 和线程 ID。
    • Shared Object:表示与该样本关联的共享库或内核对象。
bash复制代码9.61%  sleep  14852  14852  [kernel.kallsyms]
8.97%  sleep  14852  14852  linker64
6.42%  sleep  14852  14852  linker64
6.11%  sleep  14852  14852  [kernel.kallsyms]
5.83%  sleep  14852  14852  [kernel.kallsyms]
  • 解析

    • 这部分显示了在 sleep 进程运行时,消耗 CPU 资源最多的函数或操作。
    • 9.61% sleep[kernel.kallsyms] 中:表示 sleep 命令的 9.61% CPU 周期花费在内核中的某个函数中(由 [kernel.kallsyms] 表示)。
    • 8.97% sleeplinker64 中:表示 sleep 命令的 8.97% CPU 周期花费在 linker64(64 位的链接器)中。

    其他行类似,每行显示了一个函数或操作的 CPU 消耗占比。

rust复制代码Symbol
vma_link
soinfo_do_lookup_impl
BionicAllocator::alloc_impl
__follow_mount_rcu
clear_page
  • Symbol

    :显示了与上述共享对象关联的具体函数或符号名。这些符号名帮助开发者了解具体哪些函数在消耗 CPU 资源:

    • vma_link:可能是某个内核或库函数,负责内存区域的链接操作。
    • soinfo_do_lookup_impl:链接器中的符号查找实现函数。
    • BionicAllocator::alloc_impl:Bionic(Android C 库)中的内存分配函数。
    • __follow_mount_rcu:内核函数,可能与文件系统挂载点的跟踪有关。
    • clear_page:内核中的页面清理函数。