perfetto 官方文档翻译

Perfetto 翻译-核心概念-trace 配置

2023-10-29  本文已影响0人  David_zhou

前言:虽然有翻译软件,虽然有chatgpt,毕竟语言隔阂,对这个工具还是一知半解,因此想通过翻译的方式和大家来一起学习下Perfetto这个强大的工具

目录

#####################以下分割线#####################
英文原文在这里

Trace configuration

与许多始终在线的日志记录系统(例如 Linux 的 rsyslog、Android 的 logcat)不同,在 Perfetto 中,所有trace的数据源默认是关闭状态,并且仅在开关开启时才记录数据。

当正在抓取一个(或多个)trace时,才会记录数据源的数据。通过调用 perfetto cmdline 客户端并传递配置来开始抓取(请参阅适用于 AndroidLinuxChrome on desktop 的快速入门指南)。

一个简单的跟踪配置如下所示:

duration_ms: 10000

buffers {
  size_kb: 65536
  fill_policy: RING_BUFFER
}

data_sources {
  config {
    name: "linux.ftrace"
    target_buffer: 0
    ftrace_config {
      ftrace_events: "sched_switch"
      ftrace_events: "sched_wakeup"
    }
  }
}

其用法如下:

perfetto --txt -c config.pbtx -o trace_file.perfetto-trace

提示:可以在 的 repo 中找到 /test/configs/一些更完整的跟踪配置示例。

TraceConfig
trace_config.png
Buffers

缓冲区部分定义tracing service拥有的内存中缓冲区的数量、大小和策略。大体结构如下:

# Buffer #0
buffers {
  size_kb: 4096
  fill_policy: RING_BUFFER
}

# Buffer #1
buffers {
  size_kb: 8192
  fill_policy: DISCARD
}

每个缓冲区都有一个填充策略,该策略是:

警告:对于在trace末尾提交数据的数据源,DISCARD 可能会产生意外的副作用。

trace config必须至少定义一个缓冲区才能有效。在最简单的情况下,所有数据源都会将其跟踪数据写入同一缓冲区。

虽然这适用于大多数情况,但在不同数据源以明显不同的速率写入的情况下,它可能会出现问题。
例如,假设一个trace config同时支持:

  1. 内核调度程序跟踪器。在典型的 Android 手机上,这会记录 ~10000 个事件/秒,以 ~1 MB/s 的速度将trace数据写入缓冲区。
  2. 内存统计信息轮询。此数据源将 /proc/meminfo 的内容写入跟踪缓冲区,并配置为每 5 秒轮询一次,每个轮询间隔写入 约100 KB。

如果两个数据源都配置为写入同一缓冲区,并且该缓冲区设置为 4MB, ,则大多数trace将仅包含一个内存快照。大多数跟踪很有可能根本不包含任何内存快照,即使第二个数据源工作正常。这是因为在 5 秒的轮询间隔内,调度程序数据源最终可能会填满整个缓冲区,导致内存快照数据没有机会写入缓冲区。

动态缓冲区映射

数据源<>缓冲区映射在 Perfetto 中是动态的。在最简单的情况下,跟踪会话只能定义一个缓冲区。默认情况下,所有数据源都会将数据记录到该缓冲区中。
在上述示例中,最好将这些数据源分隔到不同的缓冲区中。这可以通过 TraceConfig target_buffer 的字段来实现。

trace_config_buffer_mapping.png
可以通过以下配置实现:
data_sources {
  config {
    name: "linux.ftrace"
    target_buffer: 0       # <-- This goes into buffer 0.
    ftrace_config { ... }
  }
}

data_sources: {
  config {
      name: "linux.sys_stats"
      target_buffer: 1     # <-- This goes into buffer 1.
      sys_stats_config { ... }
  }
}

data_sources: {
  config {
    name: "android.heapprofd"
    target_buffer: 1       # <-- This goes into buffer 1 as well.
    heapprofd_config { ... }
  }
}
PBTX 与二进制格式

使用 perfetto cmdline 客户端格式时,有两种方法可以传递trace config:

文本格式

它是人工驱动的工作流程和探索的首选格式。它允许直接以 PBTX(ProtoBuf TeXtual 表示)语法传递文本文件,用于 trace_config.proto中定义的模式(请参阅参考文档

When using this mode pass the --txt flag to perfetto to indicate the config should be interpreted as a PBTX file: 使用此模式时,使用 --txt 参数表示应将配置解析为 PBTX 文件:

<pre mdtype="fences" cid="n299" lang="" class="md-fences md-end-block ty-contain-cm modeLoaded" spellcheck="false" style="box-sizing: border-box; overflow: visible; font-family: Consolas, Menlo, Monaco, monospace, serif; font-size: 0.9rem; background-image: inherit; background-size: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: inherit; display: block; break-inside: avoid; text-align: left; white-space: normal; position: relative !important; margin-left: 1em; padding-left: 1em; border: 1px solid rgb(221, 221, 221); padding-bottom: 8px; padding-top: 6px; margin-bottom: 1.5em; width: inherit; background-position: inherit; background-repeat: inherit;">perfetto -c /path/to/config.pbtx --txt -o trace_file.perfetto-trace</pre>

它是机器对机器 (M2M) 交互的首选格式。它将 TraceConfig 编码为 protobuf 二进制文件。这可以将 PBTX 作为输入传递给 protobuf protoc 的编译器(可在此处下载)获得。

二进制格式

警告:不要将文本格式用于机器对机器交互基准测试、脚本和工具),因为它更容易损坏(例如,如果字段被重命名或枚举被转换为整数)

注意:该 --txt 选项仅在Android 10 (Q)中引入。旧版本仅支持二进制格式。

cd ~/code/perfetto  # external/perfetto in the Android tree.protoc --encode=perfetto.protos.TraceConfig \        -I. protos/perfetto/config/perfetto_config.proto \        < config.txpb \        > config.bin

然后将其传递给 perfetto,如下所示,不带 --txt 参数:

perfetto -c config.bin -o trace_file.perfetto-trace

流式处理长时间的trace

默认情况下,Perfetto 将完整的跟踪缓冲区保留在内存中,并仅在trace结束时将其写入目标文件( -o cmdline 参数)。这是为了减少trace系统的性能侵入性。但是,这会将trace的最大大小限制为设备的物理内存大小,这通常是有限的。 在某些情况下(例如,基准测试、难以重现的案例),希望捕获比机器物理内存大得多的trace,虽然会带来额外的 I/O 开销。

为了实现这一点,Perfetto 允许使用以下 TraceConfig 字段定期将跟踪缓冲区写入目标文件(或 stdout):

摘要:要捕获长跟踪,只需设置 ,设置 write_into_file:true 一个 long duration_ms 并使用 32MB 或更大的内存缓冲区大小。

特定数据源的配置

除了跟踪范围的配置参数外,trace config还可以定义特定于数据源的行为。在原型架构级别,这在以下 DataSourceConfig TraceConfig 部分中定义: 来自 data_source_config.proto:

message TraceConfig {
  ...
  repeated DataSource data_sources = 2;  // See below.
}

message DataSource {
  optional protos.DataSourceConfig config = 1;  // See below.
  ...
}

message DataSourceConfig {
  optional string name = 1;
  ...
  optional FtraceConfig ftrace_config = 100 [lazy = true];
  ...
  optional AndroidPowerConfig android_power_config = 106 [lazy = true];
}

ftrace_config和android_power_config这样的字段是特定数据源配置的一个示范。tracing service将完全忽略这些字段的内容,并在其他地方也使用对应名字的DataSourceConfig对象(全局生效?) 该 [lazy=true] 标记在 protozero 生成器中具有特殊的含义。与标准嵌套消息不同,

关于向后/向前兼容性的说明

tracing service会将 DataSourceConfig 消息的原始二进制 blob 路由到名字匹配的数据源,而无需尝试对其进行解码和重新编码。如果跟踪配置 DataSourceConfig 的部分包含生成服务时不存在的新字段,则服务仍将传递 DataSourceConfig 到数据源。这允许引入新的数据源,而无需服务预先了解它们的任何信息。

TODO:我们知道,今天使用自定义原型扩展需要 DataSourceConfig 更改 Perfetto 存储库 data_source_config.proto 中的 perfetto,这对于外部项目来说并不理想。长期计划是为非上游扩展保留一系列字段,并为客户端代码提供通用模板化访问器。在此之前,我们接受patches upstream,为您自己的数据源引入临时配置。

多进程数据源

某些数据源是单例的。例如,在 Perfetto 在 Android 上发布的调度程序tracing的情况下, traced_probes 整个系统只有数据源,由 traced_probes拥有。 但是,在一般情况下,多个进程可以播发同一数据源。例如,当使用 Perfetto SDK 进行用户态检测时,就是这种情况。 如果发生这种情况,则需要开始抓取trace时,在trace config中确定具体的数据来源。默认情况下,Perfetto 将要求发送该数据源的所有进程启动。

在某些情况下,可能需要进一步将数据源的启用限制为特定进程(或一组进程)。这可以通过 producer_name_filterproducer_name_regex_filter .

设置这些筛选器后,Perfetto tracing service将仅在与筛选器匹配的创建者子集中激活数据源。

示范如下:

buffers {
  size_kb: 4096
}

data_sources {
  config {
    name: "track_event"
  }
  # Enable the data source only on Chrome and Chrome canary.
  producer_name_filter: "com.android.chrome"
  producer_name_filter: "com.google.chrome.canary"
}
触发器

在大多数条件下,跟踪会话的生命周期仅与 perfetto cmdline 客户端的调用命令匹配:跟踪数据记录在 TraceConfig 传递到 perfetto 时开始,并在已过 TraceConfig.duration_ms时或 cmdline 客户端终止时结束。

Perfetto 支持基于触发器的启动或停止跟踪的模式。总体思路是在跟踪配置本身中声明:

为什么要使用触发器?为什么不能在需要时启动 perfetto 或杀死 (SIGTERM) 它?所有这一切的基本原理是安全模型:在大多数 Perfetto 部署环境中(例如,在 Android 上),只有特权实体(例如 adb shell)可以配置/启动/停止跟踪。从这个意义上说,应用是无特权的,它们无法控制tracing。 触发器为非特权应用提供了一种以有限方式控制跟踪tracing生命周期的方法。概念模型为:

/system/bin/trigger_perfetto "trigger_name"

(或者也可以仅通过配置中的 activate_triggers: "trigger_name" 字段来启动独立trace抓取过程)

有两种类型的触发器:

启动触发器

启动触发器可以仅在发生某些重大事件后激活tracing。传递具有 START_TRACING 触发器的跟踪配置会导致跟踪会话保持空闲状态(即不记录任何数据),直到触发器被触发或超过 trigger_timeout_ms 时被触发。

trace_duration_ms 和有触发器的跟踪不能同时使用。

配置示例:

# If the "myapp_is_slow" is hit, the trace starts recording data and will be
# stopped after 5s.
trigger_config {
  trigger_mode: START_TRACING
  triggers {
    name: "myapp_is_slow"
    stop_delay_ms: 5000
  }
  # If no trigger is hit, the trace will end without having recorded any data
  # after 30s.
  trigger_timeout_ms: 30000
}

# The rest of the config is as usual.
buffers { ... }
data_sources { ... }
停止触发器

STOP_TRACING触发器允许在触发器触发时提前完成跟踪。在此模式下,调用 perfetto 客户端时,跟踪将立即启动(如在一般情况)。触发器发出提前结束信号。
这可用于在飞行记录器模式下使用 perfetto。通过配置RING_BUFFERSTOP_TRACING 触发器中的缓冲区启动跟踪,跟踪将不断循环记录 ,知道检测到罪魁祸首事件时完成。对于根本原因在最近的事件(例如,应用检测到缓慢滚动或缺少帧)而言,这很关键。

配置示例:

# If no trigger is hit, the trace will end after 30s.
trigger_timeout_ms: 30000

# If the "missed_frame" is hit, the trace is stopped after 1s.
trigger_config {
  trigger_mode: STOP_TRACING
  triggers {
    name: "missed_frame"
    stop_delay_ms: 1000
  }
}

# The rest of the config is as usual.
buffers { ... }
data_sources { ... }

在 Android 上,有一些关于使用 adb shell的提示

其他资源

#####################以上分割线#####################

后记:
1 本次主要使用百度翻译,虽然被骂,但至少翻译这个工具降低了门槛。
2 英文文档中的长难句真的是又长又难,基于百度的翻译,然后自己再调整下,水平实在有限。
3 技术背景知识不够,有些专有名词不知道怎么翻译,也不知道百度翻译的是否准确,功夫在诗外。
4 万事开头难,中间难不难,还不知道。中间的事后面再说,正确一天翻译一篇。
5 虽然可能会有人不屑,但总要有人去做不起眼的小事。
6 google 厉害,这个perfetto 工具也很厉害。君子善假于物也。
7 工具的使用是最简单的入门,背后还有更多的东西值得学习。
8 水平实在有限,闻过则喜,希望有更多的人反馈,期待更好的建议

上一篇 下一篇

猜你喜欢

热点阅读