1 简介

https://www.lizenghai.com/archives/26061.html

2 用法

用命令行启动Systrace抓取采样:《Capture a system trace on the command line

自定义采样的方法:《Define custom events》这个方法确实要仔细看,尤其是采样命令的描述,强调了要使用 -a 参数,之前我忽略了这一点,导致自定义的标签总也显示不出来。

python systrace.py -a com.autonavi.amapauto -b  -o my_systrace_report.html sched freq idle am wm gfx view binder_driver hal dalvik camera input res

【坑】采用Android Device Monitor来抓取Systrace时有一个坑,就是经常出现Java heap error(因为我自动插桩所有函数,导致Systrace标签数量庞大),后来发现原因在于Monitor配置的Java堆最大值太小了,收集trace数据时需要大量的堆(怀疑是做数据合并加工)引发堆空间错误。解决方法如下:

. 找到Monitor脚本所在目录,里面有lib\monitor-x86,例如:C:\Users\liuheng.klh\AppData\Local\Android\Sdk\tools\lib\monitor-x86(或monitor-x86_64)
. 打开monitor.ini 配置文件,修改如下三项空间配置(尽可能大点就行):
-XX:MaxPermSize=1024m
-Xms2048m
-Xmx4096m

(1)实现自定义标签

在Android 6.0(API 23)中包含trace.h,可以在Native层直接进行引用,获取函数指针进行调用。用 ATRACE_CALL 宏直接在需要插桩的函数入口调用一下即可。关键代码:

 #include <android/trace.h>

 /////////////////////////////////////////////////////////////////////
// utils.h
extern void *(*_ATrace_beginSection) (const char* sectionName) __attribute__ ((no_instrument_function));
extern void *(*_ATrace_endSection) (void) __attribute__ ((no_instrument_function));
extern bool *(*_ATrace_isEnabled) (void) __attribute__ ((no_instrument_function)); // SysTrace
class ScopedTrace {
const char* _name;
public:
static bool _bInit;
static void init() __attribute__ ((no_instrument_function)); typedef void *(*fp_ATrace_beginSection) (const char* sectionName);
typedef void *(*fp_ATrace_endSection) (void);
typedef bool *(*fp_ATrace_isEnabled) (void); public:
inline ScopedTrace(const char* name) __attribute__ ((no_instrument_function)) {
if (!_bInit) {
init();
}
_ATrace_beginSection(name) ; _name = name;
//LOGD("_ATrace_beginSection(%s) _ATrace_isEnabled()=%d", name, _ATrace_isEnabled());
} inline ~ScopedTrace() __attribute__ ((no_instrument_function)) {
_ATrace_endSection();
//LOGD("_ATrace_endSection(%s) _ATrace_isEnabled()=%d", _name, _ATrace_isEnabled());
}
}; #define ATRACE_NAME(name) ScopedTrace ___tracer(name)
#define ATRACE_CALL() ATRACE_NAME(__FUNCTION__) /////////////////////////////////////////////////////////////////////
// utils.cpp
void *(*_ATrace_beginSection) (const char* sectionName) = NULL;
void *(*_ATrace_endSection) (void) = NULL;
bool *(*_ATrace_isEnabled) (void) = NULL; bool ScopedTrace::_bInit = false;
void ScopedTrace::init() {
if (_bInit) {
return;
} // Retrieve a handle to libandroid.
void *lib = dlopen("libandroid.so", RTLD_NOW || RTLD_LOCAL); // Access the native tracing functions.
if (lib != NULL) {
// Use dlsym() to prevent crashes on devices running Android 5.1
// (API level 22) or lower.
_ATrace_beginSection = reinterpret_cast<fp_ATrace_beginSection>(
dlsym(lib, "ATrace_beginSection"));
_ATrace_endSection = reinterpret_cast<fp_ATrace_endSection>(
dlsym(lib, "ATrace_endSection"));
_ATrace_isEnabled = reinterpret_cast<fp_ATrace_isEnabled>(
dlsym(lib, "ATrace_isEnabled"));
} LOGI("lib=%p, _ATrace_beginSection=%p, _ATrace_endSection=%p, _ATrace_isEnabled=%p, ATrace_isEnabled()=%d",
lib, _ATrace_beginSection, _ATrace_endSection, _ATrace_isEnabled, _ATrace_isEnabled()); _bInit = true;
}

Systrace(Native)

(2)一个巧妙的利用——编译器自动插桩

利用gcc的 “-finstrument-functions” 可以实现自动化插桩。关键代码如下:

 // utils.h
extern "C" { void __cyg_profile_func_enter( void *, void * ) __attribute__ ((no_instrument_function));
void __cyg_profile_func_exit( void *, void * ) __attribute__ ((no_instrument_function)); } // utils.cpp
#define DUMP(func, call) LOGI("[KLH]%s: func = %p, called by = %p\n", __FUNCTION__, func, call) extern "C" { void __cyg_profile_func_enter(void *this_func, void *call_site) {
//DUMP(this_func, call_site);
char addr[];
snprintf(addr, , "%p", this_func); ScopedTrace::init(); if ( != _ATrace_isEnabled && _ATrace_isEnabled()) {
_ATrace_beginSection(addr);
}
} void __cyg_profile_func_exit(void *this_func, void *call_site) {
//DUMP(this_func, call_site); if ( != _ATrace_isEnabled && _ATrace_isEnabled()) {
_ATrace_endSection();
}
} }

自动插桩实现追踪

这里关键的点是需要extern "C"声明原型。

(3)编写一套Python(其他语言也行)工具来翻译加工自动插桩的函数(运行时)地址为函数名。翻译的方法为:

. 获取进程pid:
adb shell ps | adb shell grep [进程名]
分解字符串第一个即是 . 获取进程maps
adb shell cat /proc/[pid]/maps . 提取trace.html(Systrace报告)中所有运行时地址列表,准备翻译 . 提取所有so的地址段,以此来确定运行时地址所属so及内部相对地址 . 提取so内部相对地址与符号映射表
readelf -sW libXXX.so . 根据4、5翻译出运行时地址对应的函数符号,并翻译出函数名
c++filt -n [symbol] . trace.html中线程名缺失的问题可以进一步补充(如果线程中途退出则可能遗漏):
adb shell cat /proc/pid/task
[foreach] tid
adb shell cat /proc/pid/task/tid/status
得到Name:字段就是线程名称

3 原理

Android之Systrace的更多相关文章

  1. Android性能优化之Systrace工具介绍(一) _&& Systrace生成的trace.html打开空白或者打不开的解决办法

    1.必须用Chrome打开 2.在mac电脑上,可能Chrome打开也是空白,解决办法是:在chrome地址栏中输入”chrome:tracing”,然后点击load按钮load你的trace.htm ...

  2. Android性能优化工具之Systrace

    本文大部分内容来自:http://www.androidperformance.com/android-performance-tools-systrace-1.html?utm_source=tui ...

  3. Android 常用的性能分析工具详解:GPU呈现模式, TraceView, Systrace, HirearchyViewer(转)

    此篇将重点介绍几种常用的Android性能分析工具: 一.Logcat 日志 选取Tag=ActivityManager,可以粗略地知道界面Displaying的时间消耗.当我们打开一个Activit ...

  4. Android性能分析Systrace工具

    一.概述 保证系统流畅度,也就是保证系统能连续不间断地提供每秒60帧的运行状态.当出现掉帧时(也可称为Jank),需要知道当前整个系统所处的状态,systrace便是最佳的选择,它能手机检测Andro ...

  5. Android 性能优化(25)*性能工具之「Systrace」Analyzing UI Performance with Systrace:用Systrace得到ui性能报告

    Analyzing UI Performance with Systrace In this document Overview 简介 Generating a Trace  生成Systrace文件 ...

  6. android性能測试systrace

    一:简单介绍 systrace 是 Android4.1 引入的一套用于做性能分析的工具. 基于 Linux 内核的 ftrace 机制(用于跟踪 Linux 内核的函数调用), 能够输出各个线程当前 ...

  7. Android:通过systrace进行性能分析

    一.Systrace 简介 Systrace 允许您在系统级别(如SurfaceFlinger.WindowManagerService等Framework部分关键模块.服务.View系统等)收集和检 ...

  8. Android UI性能测试——使用 Systrace 查找问题

    一 官方文档翻译 官文地址:https://developer.android.com/studio/command-line/systrace systrace命令允许您在系统级别上收集和检查所有运 ...

  9. [Android systrace系列] systrace入门第一式

    转载请注明出处:https://www.cnblogs.com/zzcperf/p/13978915.html Android systrace是分析性能问题最称手的工具之一,可以提供丰富的手机运行信 ...

随机推荐

  1. 十九.部署LNMP环境、构建LNMP平台、地址重写

    proxy client web1 web2   1.部署LNMP环境 1.1 部署nginx(前面已部署过) 1.2 部署mariadb ]# yum -y install mariadb mari ...

  2. Linq找不到行或行已更改

    1.发生这种情况第一时间是确认了database明明存在这条数据 2.然后确认了Linq查找的条件中是否有连接条件使得连续更新中发生变化 3.最后发现原来是Linq使用的表实际中有个field由not ...

  3. 使用webuploader实现大文件断点续传

    IE的自带下载功能中没有断点续传功能,要实现断点续传功能,需要用到HTTP协议中鲜为人知的几个响应头和请求头. 一. 两个必要响应头Accept-Ranges.ETag 客户端每次提交下载请求时,服务 ...

  4. [Luogu] 外星密码

    https://www.luogu.org/problemnew/show/P1928 沙比提 读清题目 #include <bits/stdc++.h> using namespace ...

  5. P1143 进制转换

    漂亮小姐姐点击就送:https://www.luogu.org/problemnew/show/P1143 题目描述 请你编一程序实现两种不同进制之间的数据转换. 输入输出格式 输入格式: 输入数据共 ...

  6. C++类的介绍

    最近在学习SLAM,顺便将C++类的知识复习一下.(其中部分官方定义和程序设计方法来源于西北工业大学魏英老师)   1.类的定义: 是用户自定义的数据类型. C++一个类定义的形式如下: class ...

  7. IDEA Junit FileNotFoundException: class path resource [spring/spring.xml] cannot be opened because it does not exist

    今天打算写一个单元测试,但是已经有写好的单元测试无论怎么弄都提示文件不存在,自己一度以为是启动方式不正确.这里简单记录一下处理过程 1 异常信息: Caused by: org.springframe ...

  8. 跑shell脚本出错问题以及解决。

    脚本信息: #!/bin/bash function hello(){ cat <<YJT echo "hello world!!!" YJT } hello 错误: ...

  9. 深入理解JVM——关于垃圾回收

    关于垃圾回收 仿佛来自上海居委会大妈的灵魂拷问:“你是什么垃圾?” 不 今天我们要说的是JVM的垃圾回收 假如我是一个“人”类的“对象”,也和人的生命一样必有一死,可是“我真的还想再活500年~~”, ...

  10. 系统调优:如何解决系统报错too many open files

    一.检查系统版本是否手工升级 关于lsb_release -a和/etc/issue显示的发行版本号不同,原因只有一个:系统内核手动升级了 对于高并发高http连接的应用程序例如www或Java,会遇 ...