性能优化必学基础:perfetto/systrace添加抓取trace块java/c++方法汇总

Perfetto Trace:从命令行到可视化分析的完整指南 本文详细介绍了Perfetto Trace工具在Android性能分析中的应用,从命令行数据采集到可视化分析的完整流程。作为Android平台新一代性能分析利器,Perfetto支持多维度数据融合和高精度时间轴分析,帮助开发者快速定位卡顿、耗电等性能问题。文章包含实战配置示例和优化策略,是移动开发者的必备指南。 阅读详情
AI摘要

本文详细介绍了在不同开发场景下如何为perfetto/systrace添加trace块。涵盖了Java和C++语言在平台私有代码及SDK/NDK环境下的埋点方式,包括同步块、计数块和异步块的实现方法,并提供了具体的代码示例。

背景:

经常大家做系统性能优化时候,会使用抓取perfetto的trace来进行分析,主要就是分析perfetto上的各个执行块耗时长短,或者说count计数块等。
具体如下图所示:
在这里插入图片描述这些perfetto上展示的执行块slice,其实一般都是在aosp的原生代码中进行的埋点,简单说看到每个slice其实都是有对应的埋点代码,当然这个代码可能是java,c++等,而且哪怕都是java和c++这种也分为是基于源码编译的java,c++代码还是说基于sdk和ndk的java、c++代码,这些都是有差异的,所以针对这些不同的代码和编译情况今天都进行汇总,给大家展示应该如何在自己程序埋入perfetto的slice。
主要会汇总以下4个部分的代码:

原生开发的两个

Java(platform private)
c/c++(platform private)

SDK和NDK开发的两个

Java(SDK)
c/c++(NDK)

perfetto中trace设置的方法汇总

普通线程执行的同步块

Thread-scoped synchronous slices

最为常见的一种slice设置方法,主要就是在要执行体的前后加trace埋点接口方法既可以

Java(platform private)
比如framework开发可以修改原生的java源码情况,就可以使用该方法

代码参考:
frameworks/base/core/java/android/os/Trace.java

案例

import android.os.Trace;
import static android.os.Trace.TRACE_TAG_AUDIO;

public void playSound(String path) {
  Trace.traceBegin(TRACE_TAG_AUDIO, "PlaySound");
  try {
    // Measure the time it takes to open the sound sevice.
    Trace.traceBegin(TRACE_TAG_AUDIO, "OpenAudioDevice");
    try {
      SoundDevice dev = openAudioDevice();
    } finally {
      Trace.traceEnd();
    }

    for(...) {
      Trace.traceBegin(TRACE_TAG_AUDIO, "SendBuffer");
      try {
        sendAudioBuffer(dev, ...)
      } finally {
        Trace.traceEnd();
      }
      // Log buffer usage statistics in the trace.
      Trace.setCounter(TRACE_TAG_AUDIO, "SndBufferUsage", dev->buffer)
      ...
    }
  } finally {
    Trace.traceEnd();  // End of the root PlaySound slice
  }
}

c++(platform private)

比如framework开发可以修改原生的c++源码情况,就可以使用该方法
案例

// ATRACE_TAG is the category that will be used in this translation unit.
// Pick one of the categories defined in Android's
// system/core/libcutils/include/cutils/trace.h
#define ATRACE_TAG ATRACE_TAG_AUDIO

#include <cutils/trace.h>

void PlaySound(const char* path) {
  ATRACE_BEGIN("PlaySound");

  // Measure the time it takes to open the sound sevice.
  ATRACE_BEGIN("OpenAudioDevice");
  struct snd_dev* dev = OpenAudioDevice();
  ATRACE_END();

  for(...) {
    ATRACE_BEGIN("SendBuffer");
    SendAudioBuffer(dev, ...)
    ATRACE_END();

    // Log buffer usage statistics in the trace.
    ATRACE_INT("SndBufferUsage", dev->buffer);
    ...
  }

  ATRACE_END();  // End of the root PlaySound slice
}

Java(SDK)
比如普通的app开发就需要使用该方法

参考: https://developer.android.com/reference/android/os/Trace
案例

// You cannot choose a tag/category when using the SDK API.
// Implicitly all calls use the ATRACE_TAG_APP tag.
import android.os.Trace;

public void playSound(String path) {
  try {
    Trace.beginSection("PlaySound");

    // Measure the time it takes to open the sound sevice.
    Trace.beginSection("OpenAudioDevice");
    try {
      SoundDevice dev = openAudioDevice();
    } finally {
      Trace.endSection();
    }

    for(...) {
      Trace.beginSection("SendBuffer");
      try {
        sendAudioBuffer(dev, ...)
      } finally {
        Trace.endSection();
      }

      // Log buffer usage statistics in the trace.
      Trace.setCounter("SndBufferUsage", dev->buffer)
      ...
    }
  } finally {
    Trace.endSection();  // End of the root PlaySound slice
  }
}

c/c++(NDK)

比如普通的app的NDK开发,就需要使用该方法

参考:https://developer.android.com/ndk/reference/group/tracing
案例

// You cannot choose a tag/category when using the NDK API.
// Implicitly all calls use the ATRACE_TAG_APP tag.
#include <android/trace.h>

void PlaySound(const char* path) {
  ATrace_beginSection("PlaySound");

  // Measure the time it takes to open the sound sevice.
  ATRACE_BEGIN("OpenAudioDevice");
  struct snd_dev* dev = OpenAudioDevice();
  ATrace_endSection();

  for(...) {
    ATrace_beginSection("SendBuffer");
    SendAudioBuffer(dev, ...)
    ATrace_endSection();

    // Log buffer usage statistics in the trace.
    ATrace_setCounter("SndBufferUsage", dev->buffer)
    ...
  }

  ATrace_endSection();  // End of the root PlaySound slice
}

计数块

Counters
主要用于一些计数相关的统计,比如Input分析时候需要IQ,OQ,WQ这些值。
数值的改变可以任何线程调用触发对Counter值的改变
在这里插入图片描述
那么这些计数块如何在程序中进行埋点设置呢?

Java(platform private)

使用案例

import android.os.Trace;
import static android.os.Trace.TRACE_TAG_AUDIO;

public void playSound(String path) {
  SoundDevice dev = openAudioDevice();
  for(...) {
    sendAudioBuffer(dev, ...)
    ...
    // Log buffer usage statistics in the trace.
    Trace.setCounter(TRACE_TAG_AUDIO, "SndBufferUsage", dev->buffer.used_bytes)
  }
}

c++(platform private)

使用案例

// ATRACE_TAG is the category that will be used in this translation unit.
// Pick one of the categories defined in Android's
// system/core/libcutils/include/cutils/trace.h
#define ATRACE_TAG ATRACE_TAG_AUDIO

#include <cutils/trace.h>

void PlaySound(const char* path) {
  struct snd_dev* dev = OpenAudioDevice();

  for(...) {
    SendAudioBuffer(dev, ...)

    // Log buffer usage statistics in the trace.
    ATRACE_INT("SndBufferUsage", dev->buffer.used_bytes);
  }
}

Java(SDK)
使用案例

// You cannot choose a tag/category when using the SDK API.
// Implicitly all calls use the ATRACE_TAG_APP tag.
import android.os.Trace;

public void playSound(String path) {
  SoundDevice dev = openAudioDevice();

  for(...) {
    sendAudioBuffer(dev, ...)

    // Log buffer usage statistics in the trace.
    Trace.setCounter("SndBufferUsage", dev->buffer.used_bytes)
  }
}

c/c++(NDK)

使用案例

// You cannot choose a tag/category when using the NDK API.
// Implicitly all calls use the ATRACE_TAG_APP tag.
#include <android/trace.h>

void PlaySound(const char* path) {
  struct snd_dev* dev = OpenAudioDevice();

  for(...) {
    SendAudioBuffer(dev, ...)

    // Log buffer usage statistics in the trace.
    ATrace_setCounter("SndBufferUsage", dev->buffer.used_bytes)
  }
}

异步块

上面最开始有介绍同步块,也就是必须在一个线程中执行,Android其实是支持异步trace的,源码中应用的比较多,在代码中打上异步trace就不需要保证在一个线程之中,也不要求一定要把一段代码包起来,这种可能平时自己开发时候使用较少,下面以一个案例说明。

跟踪一个动画的开始与结束,可以看出它的执行时长,和同步执行那种单线程完全不一样。
在这里插入图片描述对应的代码:
在这里插入图片描述

Java(platform private)

使用案例

import android.os.Trace;
import static android.os.Trace.TRACE_TAG_NETWORK;

public class AudioRecordActivity extends Activity {
  private AtomicInteger lastJobId = new AtomicInteger(0);
  private static final String TRACK_NAME = "User Journeys";

    ...
    button.setOnClickListener(v -> {
        int jobId = lastJobId.incrementAndGet();
        Trace.asyncTraceForTrackBegin(TRACE_TAG_NETWORK, TRACK_NAME, "Load profile", jobId);

        // Simulate async work (e.g., a network request)
        new Thread(() -> {
            Thread.sleep(800); // emulate latency
            Trace.asyncTraceForTrackEnd(TRACE_TAG_NETWORK, TRACK_NAME, jobId);
        }).start();
    });
    ...
}

c++(platform private)

使用案例

// ATRACE_TAG is the category that will be used in this translation unit.
// Pick one of the categories defined in Android's
// system/core/libcutils/include/cutils/trace.h
#define ATRACE_TAG ATRACE_TAG_NETWORK

#include <cutils/trace.h>
#include <thread>
#include <chrono>
#include <atomic>

static constexpr const char* kTrackName = "User Journeys";

void onButtonClicked() {
  static std::atomic<int> lastJobId{0};

  int jobId = ++lastJobId;
  ATRACE_ASYNC_FOR_TRACK_BEGIN(kTrackName, "Load profile", jobId);

  std::thread([jobId]() {
      std::this_thread::sleep_for(std::chrono::milliseconds(800));
      ATRACE_ASYNC_FOR_TRACK_END(kTrackName, jobId);
  }).detach();
}

Java(SDK)
使用案例

// You cannot choose a tag/category when using the SDK API.
// Implicitly all calls use the ATRACE_TAG_APP tag.
import android.os.Trace;

public class AudioRecordActivity extends Activity {
  private AtomicInteger lastJobId = new AtomicInteger(0);

    ...
    button.setOnClickListener(v -> {
        int jobId = lastJobId.incrementAndGet();
        Trace.beginAsyncSection("Load profile", jobId);

        // Simulate async work (e.g., a network request)
        new Thread(() -> {
            Thread.sleep(800); // emulate latency
             Trace.endAsyncSection("Load profile", jobId);
        }).start();
    });
    ...
}

c/c++(NDK)

使用案例

// You cannot choose a tag/category when using the NDK API.
// Implicitly all calls use the ATRACE_TAG_APP tag.
#include <android/trace.h>
#include <thread>
#include <chrono>
#include <atomic>

void onButtonClicked() {
  static std::atomic<int> lastJobId{0};

  int jobId = ++lastJobId;
  ATrace_beginAsyncSection("Load profile", jobId);

  std::thread([jobId]() {
      std::this_thread::sleep_for(std::chrono::milliseconds(800));
      ATrace_endAsyncSection("Load profile", jobId);
  }).detach();
}

上面就是针对perfetto/systrace进行埋点相关slice的详细介绍,更多framework实战开发,可以关注下面“千里马学框架”

Android中如何通过perfetto抓取trace 借助config文件配置要调试的内容,命令行如下,其中config.pbtx为config file,可以借助Perfetto UI的recording setting(Perfetto UI)生成,或者在Perfetto UI中的redording settings中设置后好,在recording command 中copy所有内容,在terminal中直接copy执行即可。可以看到,我们通过这种的方式也是抓取成功的,通过 config 的方式我们可以自定义抓取规则,更大的契合了各种业务的需要。 阅读详情

相关推荐

如何使用Perfetto通过trace分析性能问题(四)——Trace Processor

Trace processor, perfetto, trace

m0_37999066的博客 3018

【android 性能分析之perfetto_trace抓取】

配置好了要抓哪些信息以后还需要配置抓取的时间以及文件大小.如果不是需要长时间抓取的话,如下配置就行,会抓取十秒这样.如果需要抓很长事件可以使用long trace模式,然后把Max duration和Max file size拉大.点击左边的下载就可以把trace下载到本地,上面的Json会丢失信息,一般不使用,systrace格式信息是完整的,用这个最好.自带的trace信息不一定能明确问题点,可以在怀疑的代码中自己加上trace。有时候需要和别人协同分析,那么就需要把trace文件同步给别人.

qq_25815655的博客 3127

C#:WPF格式转Winform格式

WPF格式转Winform格式

Hello C++ 1295

perfetto命令 抓取 trace

2.再打开一个 CMD 窗口,设置 traced 权限。其中 -t 10s 意思就是抓取 10 秒。可以看到10秒后自动结束记录 trace 了。3.验证是否打开 traced 权限。4. 输入 perfetto 命令。进入到 cmd 中,敲入下面的命令。可以看到拷贝好的 trace 文件。1.启动Android 模拟器。然后把 trace 文件拖进来。5.拷贝 trace 到电脑。点击照相APP,操作几下。

hugang的博客 5180

硬件作品3----STM32F103RCT6最小系统板MCU配置

电路未调试成功,目前刚打板,后续需要补充或者改版另行注明。

weixin_58364194的博客 5562

Fleury算法寻找欧拉回路(mtlab代码详解)

【代码】Fleury算法寻找欧拉回路(mtlab代码详解)

m0_63449998的博客 1296

如何使用Perfetto通过trace分析性能问题(五)——Trace-based metrics

trace processor, protobuf

m0_37999066的博客 2965

Unity 调用安卓内部安装apk

一、申请权限 应用内安装其他应用的权限属于特殊权限,需要在特殊申请。 Uri packageURI = Uri.parse("package:" + mContext.getPackageName()); Intent intent = new Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES, packageURI); startA...

BDDNH的博客 1240

抓trace perfetto分析

prefetto 抓trace

b1tb1t的博客 1178

RK3568移植AP6256

本文主要是记录RK3568移植正基的AP6256的WIFIBT模块,感兴趣的朋友可以一起学习!!!提示:以下是本篇文章正文内容,下面案例可供参考。

qq_24093081的博客 3715

AI应用架构师实战:超算中AI与量子计算融合的初探与架构

当大模型的算力需求突破E级超算的极限,当量子计算的“量子优势”从实验室走向真实场景,超算+AI+量子计算的融合架构成为解决复杂问题的关键路径。本文从架构师的实战视角出发,系统拆解三者融合的底层逻辑:从“计算本质”的第一性原理推导,到“量子-经典异构”的架构设计;从“量子机器学习”的代码实现,到“金融/医药”的场景落地。我们将回答:如何用超算支撑量子计算的噪声抑制与纠错?如何用量子计算加速AI模型的训练与推理?如何设计可扩展、高可用的融合系统?最终给出架构师的实战指南——从技术选型到运营管理的全流程方法论。

AIGC应用创新大全的博客 924

Android 卡顿验证方法1:系统跟踪 Perfetto

Android 卡顿验证方法1:系统跟踪 Perfetto

marchlqq的专栏 5933

2025.06.18【转录组】|Ribo-seq/small RNA数据分析:rRNA和smRNA比对率统计全流程

本文介绍了一种自动化统计rRNA/smRNA比对率的方法,用于评估Ribo-seq或small RNA测序数据的质量。主要内容包括:分析原理(比对率定义、参考序列来源)、实践流程(构建索引、比对统计)以及结果可视化方法。通过Python和R脚本实现自动化处理,可生成汇总表格和柱状图。比对率结果能反映样品污染程度,建议控制在20%以下。该流程有助于快速评估测序质量,为后续分析提供可靠依据。文中还提供了常见问题解决方案和脚本示例,适用于生物信息学标准化质控环节。

1616

Perfetto trace使用技巧

4.通过追踪GPU Completion定位应用卡顿的时间点,60HZ的屏幕一帧的时间为16.6ms左右,应用的GPU Completion表示该帧在绘制指令结束之后多长时间GPU完成了该帧,如果绘制指令的时间+GPU Completion时间超过了16.6ms,那么就会出现丢帧,当丢帧较多时,在屏幕上很容易看到卡顿。部分机型抓取过长的trace会导致解析出错,从而无法分析,在大部分机型上可以使用5-10秒长度,过长过大的trace通常也不利于分析。

522

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

使用perfetto分析trace文件

perfetto分析trace文件

weixin_45612598的博客 1979

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

利用pefertto分析trace方法【OHOS】

bigge_L的博客 7万+

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

Perfetto 快速上手指南

Perfetto 是 google 从 Android10 开始引入的一个全新的平台级跟踪分析工具。它可以记录 Android 系统运行过程中的关键数据,并通过图形化的形式展示这些数据。Perfetto 不仅可用于系统级的性能分析,也是我们学习系统源码流程的好帮手。

chuyouyinghe的专栏 5718

Android Perfetto Trace性能分析

本文介绍了 Perfetto 配置生成、抓取 Trace、使用 Perfetto UI 分析 Trace 三块内容。在 Trace 分析时主要介绍了基于 CPU 的分析,没有介绍 GPU、内存、电量分析的细节,因为日常工作中本人用的不是很多,所以暂时写不了就不误导读者了,有机会再补充一篇文章。本文介绍的内容是不到官网的 1/3 的,但是一些细节也是官网没有的,很多人在实操时就卡在这些细节上,这也是我写这篇文章的原因。

布莱克‌ 2万+

Android性能优化--Perfetto抓取trace

开启Android的trace跟踪服务; 使用 adb 抓取; 通过 perfetto 网页抓取; 直接在手机上抓取; 使用 record_android_trace 抓取; 熟悉 perfetto 快捷键,会有事半功倍效果;

分享Android应用和系统开发、音视频编码、性能优化相关知识 4549

通Perfetto解析trace日志,分析启动速度慢的问题

首先打开trace的文件,然后标记对应的应用,以及launch应用,以及启动应用的动画animator可以看到如下:分析如下:1.第一个是启动的应用usb,第二个是usb的运行情况,第三行数是usb启动的动画,第四行是launcher的启动动画,后面就是launcher的点击运行的主线程。2、我们可以根据动画效果可以看到一开始是launcher的启动动画,然后是usb的启动动画显示。

qq_35770839的博客 1395

Perfetto详细解析

本篇文章主要介绍Perfetto的详细使用,以及各个模块在Perfetto上的表现,如何对手机性能做基本分析,如何判断卡顿等进行解析,后续会出相关的实战文章。

Android系统优化 3万+

Perfetto分析进阶

一、Perfetto介绍Perfetto是AndroidQ中引入的全新下一代平台级跟踪工具,为Android、Linux和Chrome平台提供了一种通用的性能检测和跟踪分析工具集。其核心是引入了一种全新的用户空间到用户空间的跟踪协议,该协议基于protobuf序列化机制将抓取的数据填充到共享内存缓冲区,可用于获取平台内部的内置数据源(例如ftrace、atrace、logcat),也提供了SDK...

内核工匠 3万+

Systrace 和 Perfetto的使用

systrace 和per的使用

he980725866的博客 6667
上一篇: 自由窗口圆角无效/ubuntu无法用wifi/输入窗口层次/user版本pull出data下文件-vip学员近期答疑问题汇总
下一篇: google官方性能文档:Android 动态性能框架优化散热和 CPU 性能-Thermal API部分
千里马学框架
博客等级 码龄6年 1万+粉丝 650原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

千里马学框架

帮助你了,就请我喝杯咖啡

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值