记录并直观呈现轨迹

本页介绍了如何使用 Fuchsia 跟踪系统在 Fuchsia 设备上记录和直观呈现轨迹。

前提条件

许多现有的 Fuchsia 组件已注册为跟踪提供程序,其跟踪数据通常提供对系统的全面概览。因此,如果您只需要记录一般轨迹(例如,为了在 bug 报告中包含详细信息),可以继续学习以下部分。但是,如果您想从特定组件收集其他自定义跟踪事件,需要先完成以下任务:

录制轨迹

如需从宿主机在 Fuchsia 设备上录制跟踪记录,请运行以下命令:

ffx trace start --duration <SECONDS>

此命令会使用默认设置启动跟踪记录,从而捕获目标设备的总体概览。

跟踪记录会持续指定时长(如果未指定时长,则会持续到按下 ENTER 键为止)。轨迹文件完成后,轨迹数据会自动保存到当前目录中的 trace.fxt 文件(可以通过指定 --output 标志进行更改,例如 ffx trace start --output <FILE_PATH>)。如需直观呈现此文件中存储的轨迹结果,请参阅下面的直观呈现轨迹部分。

直观呈现跟踪记录

Fuchsia 轨迹格式 (.fxt) 是 Fuchsia 的二进制格式,可直接对原始轨迹数据进行编码。如需直观呈现 .fxt 轨迹文件,您可以使用 Perfetto 查看器

请执行以下操作:

  1. 在网络浏览器中访问 Perfetto 查看器网站。
  2. 点击导航栏上的 Open trace file
  3. 从主机中选择 .fxt 文件。

在此查看器中,您还可以使用 SQL 查询跟踪记录数据

附录

Fuchsia 跟踪系统以前支持各种文件格式以及直观呈现轨迹的不同方式。以下部分介绍了与现已废弃的轨迹格式相关的工作流。

(已弃用)直观呈现 JSON 跟踪记录

JSON 跟踪记录是一种在 Chrome 浏览器上查看跟踪记录数据的格式。

如需将 .fxt 跟踪文件转换为 JSON 格式,请运行以下命令:

fx trace2json < <FXT_FILE> > trace.json

FXT_FILE 替换为 FXT 跟踪文件,例如:

$ fx trace2json < trace.fxt > trace.json

如需直观呈现 JSON 跟踪记录,请使用 Chrome 浏览器内置的 Chromium Trace-Viewer

请执行以下操作:

  1. 在 Chrome 浏览器中打开一个新标签页。
  2. 进入“chrome://tracing”。
  3. 点击 Load 按钮。
  4. 打开 JSON 轨迹文件。

如需详细了解 Chromium 的 Trace-Viewer,请参阅 Trace 事件性能剖析工具

(已弃用)直观呈现 HTML 跟踪记录

HTML 跟踪记录是一个包含查看者和跟踪记录数据的独立文件。

要生成 HTML 跟踪记录,您可以使用 Chromium Catapult 代码库中的 trace2html 工具转换现有的 JSON 跟踪文件。

从 Catapult 代码库中运行以下命令:

./tracing/bin/trace2html <JSON_TRACE_FILE>

生成 HTML 轨迹文件后,您可以在任何网络浏览器中打开该文件以分析轨迹结果。

如需浏览 HTML 跟踪文件的相关信息,不妨使用下面这些实用的键盘快捷键:

  • ws:分别用于放大和缩小。缩放功能基于鼠标的当前位置。
  • WS:分别以较大比例放大和缩小。缩放功能基于鼠标的当前位置。
  • ad:分别向左和向右平移。
  • AD:分别以较大比例向左和向右平移。

此外,您还可以取消选择特定进程行,以移除对当前跟踪记录不重要的进程。如需取消选择特定进程行,请点击进程行右上角的 x

(已弃用)分析 HTML 跟踪记录

本演示介绍了在网络浏览器上生成 HTML 跟踪文件和分析结果的工作流。本演示中的示例记录了 Fuchsia 系统的跟踪记录,同时持续运行 du 命令,该命令会扫描并生成系统的磁盘使用量。

生成轨迹数据并将其转换为 HTML 文件

如需录制 du 的轨迹并将其转换为 HTML 轨迹文件,请执行以下操作:

  1. (可选)如果您没有正在运行的 Fuchsia 设备,请在启用网络功能的 Fuchsia 模拟器上启动实例:

    ffx emu --net tap
    
  2. 在新终端中,启动跟踪记录:

    ffx trace start --buffer-size 64 --categories all
    

    此命令将录制缓冲区空间设置为 64 MB,并记录所有跟踪类别。

  3. 在 Fuchsia 模拟器的控制台中,运行以下命令:

    /boot/bin/sh -c "'\
       sleep 2 ;\
       i=0 ;\
       while [ \$i -lt 10 ] ;\
       do /bin/du /boot ;\
           i=\$(( \$i + 1 )) ;\
       done'"
    

    此命令会循环运行 du

  4. 如需完成跟踪,请在运行 ffx trace start 的终端中按 Enter 键。

    完成后,该命令会生成 trace.fxt 文件。

  5. 将此 FXT 文件转换为 JSON 格式:

    fx trace2json < trace.fxt > trace.json
    
  6. 生成 HTML 跟踪记录:

    ./tracing/bin/trace2html trace.json
    
  7. 在网络浏览器中打开此 HTML 文件。

    Trace 界面的屏幕截图

    图 1. 记录循环中 du 进程的 HTML 跟踪文件的屏幕截图。

    轨迹文件包含大量信息,包括轨迹顶部附近的时间刻度。在上面的示例中,整个跟踪记录持续约 2.5 秒。

检查 CPU 使用率

图 1 中黄色圆圈标记的区域显示了 CPU 使用率,您可以在其中看到所有 CPU 核心上的总体 CPU 使用率。

检查程序执行

图 1 中绿色圆圈标记的区域显示了程序的执行情况。

在本例中,您可以看到 du 程序的 10 次调用,这是正常现象,因为轨迹记录是在 du 循环期间记录的。因此,您可以看到 10 个不同的 du 进程 ID,一个接一个。

检查 blobfs CPU 使用情况

图 1 中蓝色圆圈标记的区域显示了写入 Blob 存储区文件系统 (blobFS) 的 CPU 使用情况。

在此示例中,您可以看到与 du 的调用相关的少量 CPU 时间爆发。在这种较高层面上,可能很难确定 CPU 使用率与文件系统之间的确切相关性,例如,原因如下:

  • CPU 使用率是否是由文件系统中加载 du 引起的?
  • 执行 du 通过目标文件系统运行查看当前占用了多少空间时,是否会导致 CPU 使用率?

您可以放大该区域的特定区域,以确定 CPU 使用率与文件系统之间的关系(参见图 2)。

放大 CPU 和文件系统信息的屏幕截图

图 2. HTML 跟踪文件已放大到某个区域的屏幕截图。

在此示例中,您只能看到两个 du 执行(第一个标有绿色圆圈)。第一个 blobfs CPU 爆发实际上由三个主要集群和一些较小的峰值组成。后续的 blobfs CPU 爆发有两个集群。

通过分析此示例,您可以看到 blobfs 爆发发生在 du 程序执行之前。此信息表明,blobfs 爆发不是由 du 程序读取文件系统导致的。而是指出爆发是由于加载 du 程序所致。

现在,您可以进一步深入了解导致 blobs 爆发的原因了。

blob 跟踪时间图片

图 3. HTML 跟踪文件的屏幕截图,其时间尺度为约 1 毫秒。

在此示例中,请注意从 2,023,500 微秒到刚刚超过 2,024,500 毫秒的时间范围,表示时间尺度约为 1 毫秒。在这毫秒内,blobfs 执行了代码,从标识为 FileReadAt 的进程开始,该进程随后调用 Blob::Read,后者随后调用 Blob::ReadInternal

若要将此信息与代码相关联,您可以点击报告的各个部分,以获取有关特定对象的更多详细信息:

  • 如果您点击 FileReadAt,则可能会看到类似于以下内容的信息:

    FileReadAt 信息的图片

    此信息会告诉您以下内容:

    • FileReadAt 的轨迹类别为 vfs
    • 函数执行的时长。

    如需了解如何对 FileReatAt 执行跟踪,请参阅 //src/storage/lib/vfs/cpp/connection/connection.cc

  • 如果您点击 Blob::Read,则可能会看到类似于以下内容的信息:

    Blob::Read 信息的图片

    Blob::Read 的代码如下:

    zx_status_t Blob::Read(void* data,
                           size_t len,
                           size_t off,
                           size_t* out_actual) {
        TRACE_DURATION("blobfs", "Blob::Read", "len", len, "off", off);
        LatencyEvent event(&blobfs_->GetMutableVnodeMetrics()->read,
                           blobfs_->CollectingMetrics());
    
        return ReadInternal(data, len, off, out_actual);
    }
    

    此代码调用类别为 blobfs、名称为 Blob::Read 以及长度和偏移量键值对的 TRACE_DURATION() 宏。所有这些信息都会记录在跟踪文件中。

    如需了解如何对 Blob::Read 执行跟踪,请参阅 //src/storage/blobfs/blob.cc