Android——systrace使用分析
2015-09-11 16:23
1186 查看
前文有分析使用linux下的trace Linux trace使用入门 ,这里再次记录下android系统中比较实用的性能分析工具 systrace
撰写不易,转载需注明出处:/article/1531662.html本文来自 【jscese】的博客!
我这里记录一下eclipse上的使用
像前文python描述,systrace依赖kernel中的trace机制,还需额外对挂载的文件系统做权限修改,连接adb,如下:
只关注显示情况的话 ,只选取Graphics就可以,点击OK,操作样机,时间结束,保存xml文件
左边区域为对应的进程以及线程,右边为时序图,依次对应,可使用 鼠标+键盘 缩放定位想查看的区域
详细的操作点击右上的? 可查看:
如上trace数据为显示Graphics时抓取到的,为surfaceflinger 合成的时序操作
缩放查看其中的一段数据如下:
可以看到最上面的为VSYNC信号的变化时序,间隔16ms左右,按照60HZ的频率刷新,一次即为16+ms
从上图还可以看到一次surfaceflinger的合成操作 时间占用大概为3.5+ms 左右,相对整个一帧16+ms的时间来说,性能足够。
此图为视频播放时,播放器与surfaceflinger的buffer交互,图中每次合成前都有新的buffer数据丢到surfaceflinger这边,满足有新的buffer数据 + VSYNC信号的切换 才会去触发合成:
图中每次合之前的绿色小块就是queuebuffer, 所以从这里来看 影响整体合成帧率性能的 决定因素在queuebuffer的频率能否满足 VSYNC的需求,以达到60fps的效果
每一次surfaceflinger一帧 在一次VSYNC信号改变的时候,这里只抓取了核心的两个步骤:获取新的buffer 释放前一个buffer,组合buffer数据为一帧图像
可看到调用关系时间消耗组成图:
这里时序图中显示出来的函数名,是因为在其函数加了TRACE标记 去trace这个函数的生命周期
可依此来分析某个环节耗时多少,进行定位优化
比如在SurfaceFlinger.cpp 中:
可以看到TAG 为GRAPHICS 也就是为什么开始说eclipse里面只选个Graphics 就行了的原因,对应关系
函数中:
ATRACE_CALL()为开始标记,这就开始trace该函数了
这个宏定义在 \system\core\include\utils\Trace.h 中:
继续查看定义在 \system\core\include\cutils\trace.h 中:
看下TAG类型:
其中上面在SurfaceFlinger中定义成了 ATRACE_TAG_GRAPHICS
首先会去check 当前来的tag 是否 enable,会进行判断去初始化:
调转到 \system\core\libcutils\trace.c 中,只进行一次的初始化:
/sys/kernel/debug/tracing/trace_marker 是重点,为trace在kernel里面创建的文件节点
打开之后保存全局的文件描述符:atrace_marker_fd
现在回头看atrace_begin 和 atrace_end 就是向这个节点write 对应要打开的trace的开关数据
kernel中的trace驱动自然会有file operation处理
浏览个大概,细节有必要时再做分析~
撰写不易,转载需注明出处:/article/1531662.html本文来自 【jscese】的博客!
前提
systrace由kernel中的ftrace支持,kernel中的trace 配置开关编译,网上一搜很多,就不记录了systrace使用方式
网上有 这篇文章里面有记录使用方法,但是实际上很多在windows下的人安装了python环境之后依然报错,有人说就是不支持~我这里记录一下eclipse上的使用
eclipse环境下使用
相对前面在windows搭建python运行环境,google把sdk中的systrace模块功能集成到IDE里面,可以在安装好adt以及配置好sdk的eclipse中使用systrace功能,更加方便。注意事项
sdk中的platfom tool version要在18以上,保持纯净的sdk 以及adt环境,如果修改替换了其中的某些tool,有可能导致最终抓取结果trace.xml 无法正常打开。像前文python描述,systrace依赖kernel中的trace机制,还需额外对挂载的文件系统做权限修改,连接adb,如下:
adb shell chmod 777 /sys/kernel/debug adb shell stop adb shell start
使用
切换到eclipse的DDMS:
adb连接小机,开机adb root,adb连接正常的情况如下图显示样机信息及进程
点击红色标注按钮,选取关注的项目,结果存放路径,抓取时间以及buffer大小,默认为5s
只关注显示情况的话 ,只选取Graphics就可以,点击OK,操作样机,时间结束,保存xml文件
结果分析查看
使用google chrome 浏览器打开xml文件,情形如下:左边区域为对应的进程以及线程,右边为时序图,依次对应,可使用 鼠标+键盘 缩放定位想查看的区域
详细的操作点击右上的? 可查看:
如上trace数据为显示Graphics时抓取到的,为surfaceflinger 合成的时序操作
缩放查看其中的一段数据如下:
可以看到最上面的为VSYNC信号的变化时序,间隔16ms左右,按照60HZ的频率刷新,一次即为16+ms
从上图还可以看到一次surfaceflinger的合成操作 时间占用大概为3.5+ms 左右,相对整个一帧16+ms的时间来说,性能足够。
此图为视频播放时,播放器与surfaceflinger的buffer交互,图中每次合成前都有新的buffer数据丢到surfaceflinger这边,满足有新的buffer数据 + VSYNC信号的切换 才会去触发合成:
图中每次合之前的绿色小块就是queuebuffer, 所以从这里来看 影响整体合成帧率性能的 决定因素在queuebuffer的频率能否满足 VSYNC的需求,以达到60fps的效果
每一次surfaceflinger一帧 在一次VSYNC信号改变的时候,这里只抓取了核心的两个步骤:获取新的buffer 释放前一个buffer,组合buffer数据为一帧图像
可看到调用关系时间消耗组成图:
这里时序图中显示出来的函数名,是因为在其函数加了TRACE标记 去trace这个函数的生命周期
可依此来分析某个环节耗时多少,进行定位优化
比如在SurfaceFlinger.cpp 中:
#define ATRACE_TAG ATRACE_TAG_GRAPHICS
可以看到TAG 为GRAPHICS 也就是为什么开始说eclipse里面只选个Graphics 就行了的原因,对应关系
函数中:
bool SurfaceFlinger::handleMessageInvalidate() { ATRACE_CALL(); return handlePageFlip(); }
ATRACE_CALL()为开始标记,这就开始trace该函数了
调用实现逻辑
上面有说到 ATRACE_CALL() 开始打开trace,本着习性,必然得去追一下code,记录一下 不在意细节 ~这个宏定义在 \system\core\include\utils\Trace.h 中:
// ATRACE_NAME traces the beginning and end of the current scope. To trace // the correct start and end times this macro should be declared first in the // scope body. #define ATRACE_NAME(name) android::ScopedTrace ___tracer(ATRACE_TAG, name) // ATRACE_CALL is an ATRACE_NAME that uses the current function name. #define ATRACE_CALL() ATRACE_NAME(__FUNCTION__) namespace android { class ScopedTrace { public: inline ScopedTrace(uint64_t tag, const char* name) : mTag(tag) { atrace_begin(mTag,name); } inline ~ScopedTrace() { atrace_end(mTag); } private: uint64_t mTag; };
继续查看定义在 \system\core\include\cutils\trace.h 中:
看下TAG类型:
#define ATRACE_TAG_NEVER 0 // This tag is never enabled. #define ATRACE_TAG_ALWAYS (1<<0) // This tag is always enabled. #define ATRACE_TAG_GRAPHICS (1<<1) #define ATRACE_TAG_INPUT (1<<2) #define ATRACE_TAG_VIEW (1<<3) #define ATRACE_TAG_WEBVIEW (1<<4) #define ATRACE_TAG_WINDOW_MANAGER (1<<5) #define ATRACE_TAG_ACTIVITY_MANAGER (1<<6) #define ATRACE_TAG_SYNC_MANAGER (1<<7) #define ATRACE_TAG_AUDIO (1<<8) #define ATRACE_TAG_VIDEO (1<<9) #define ATRACE_TAG_CAMERA (1<<10) #define ATRACE_TAG_HAL (1<<11) #define ATRACE_TAG_APP (1<<12) #define ATRACE_TAG_RESOURCES (1<<13) #define ATRACE_TAG_DALVIK (1<<14) #define ATRACE_TAG_RS (1<<15) #define ATRACE_TAG_BIONIC (1<<16) #define ATRACE_TAG_POWER (1<<17) #define ATRACE_TAG_LAST ATRACE_TAG_POWER
其中上面在SurfaceFlinger中定义成了 ATRACE_TAG_GRAPHICS
/** * Trace the beginning of a context. name is used to identify the context. * This is often used to time function execution. */ #define ATRACE_BEGIN(name) atrace_begin(ATRACE_TAG, name) static inline void atrace_begin(uint64_t tag, const char* name) { if (CC_UNLIKELY(atrace_is_tag_enabled(tag))) { char buf[ATRACE_MESSAGE_LENGTH]; size_t len; len = snprintf(buf, ATRACE_MESSAGE_LENGTH, "B|%d|%s", getpid(), name); write(atrace_marker_fd, buf, len); } }
首先会去check 当前来的tag 是否 enable,会进行判断去初始化:
/** * atrace_init readies the process for tracing by opening the trace_marker file. * Calling any trace function causes this to be run, so calling it is optional. * This can be explicitly run to avoid setup delay on first trace function. */ #define ATRACE_INIT() atrace_init() static inline void atrace_init() { if (CC_UNLIKELY(!android_atomic_acquire_load(&atrace_is_ready))) { atrace_setup(); } } /** * Get the mask of all tags currently enabled. * It can be used as a guard condition around more expensive trace calculations. * Every trace function calls this, which ensures atrace_init is run. */ #define ATRACE_GET_ENABLED_TAGS() atrace_get_enabled_tags() static inline uint64_t atrace_get_enabled_tags() { atrace_init(); return atrace_enabled_tags; } /** * Test if a given tag is currently enabled. * Returns nonzero if the tag is enabled, otherwise zero. * It can be used as a guard condition around more expensive trace calculations. */ #define ATRACE_ENABLED() atrace_is_tag_enabled(ATRACE_TAG) static inline uint64_t atrace_is_tag_enabled(uint64_t tag) { return atrace_get_enabled_tags() & tag; }
调转到 \system\core\libcutils\trace.c 中,只进行一次的初始化:
static void atrace_init_once() { atrace_marker_fd = open("/sys/kernel/debug/tracing/trace_marker", O_WRONLY); if (atrace_marker_fd == -1) { ALOGE("Error opening trace file: %s (%d)", strerror(errno), errno); atrace_enabled_tags = 0; goto done; } atrace_enabled_tags = atrace_get_property(); done: android_atomic_release_store(1, &atrace_is_ready); } void atrace_setup() { pthread_once(&atrace_once_control, atrace_init_once); }
/sys/kernel/debug/tracing/trace_marker 是重点,为trace在kernel里面创建的文件节点
打开之后保存全局的文件描述符:atrace_marker_fd
现在回头看atrace_begin 和 atrace_end 就是向这个节点write 对应要打开的trace的开关数据
kernel中的trace驱动自然会有file operation处理
浏览个大概,细节有必要时再做分析~
相关文章推荐
- android EditText控件事件监听
- Android 实时滤镜 高斯模糊
- 二、Android应用的界面编程(二)布局管理器
- 清除android程序中的多余资源
- android 弹出选择框
- FragmentTabHost 自定义
- android项目迁移到新android studio所遇到的Gradle问题汇总
- android context的用法和遇到的问题
- Android studio jni
- Android - 百度地图打包之后出现的问题
- Android(java)学习笔记230:服务(service)之绑定服务的细节
- Android系统启动过程
- Android Skia和2D图形系统
- android中的view动画
- Android 第一个OpenGL ES程序
- android opengl es 总结
- android开发中Retrofit的使用
- Android shap selector animation 与 Toast退出问题
- Android 短信发送流程(修改版)
- android 中 view 的宽度和高度