systrace/perfetto中需要actrace打tag相关方法-车载车机framework系统开发实战

背景:

经常在看systrace、perfetto相关trace时候,其实我们主要就是看各种方法的调用tag,如下图所示
正因为有了系统中各个地方埋下的这些tag,才让我们可以根据这些方法tag分析出整个系统的运行情况。但是大家有没有想过,请问这些tag是怎么打上去的?如果我们自己要打印自己方法的tag应该怎么搞?

使用atrace相关类方法介绍

这里还需要看对应的trace源码是最全面的

路径:system/core/libcutils/include/cutils/trace.h

源码:

cpp 复制代码
/*
 * Copyright (C) 2012 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef _LIBS_CUTILS_TRACE_H
#define _LIBS_CUTILS_TRACE_H

#include <inttypes.h>
#include <stdatomic.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <sys/cdefs.h>
#include <sys/types.h>
#include <unistd.h>
#include <cutils/compiler.h>

__BEGIN_DECLS

/**
 * The ATRACE_TAG macro can be defined before including this header to trace
 * using one of the tags defined below.  It must be defined to one of the
 * following ATRACE_TAG_* macros.  The trace tag is used to filter tracing in
 * userland to avoid some of the runtime cost of tracing when it is not desired.
 *
 * Defining ATRACE_TAG to be ATRACE_TAG_ALWAYS will result in the tracing always
 * being enabled - this should ONLY be done for debug code, as userland tracing
 * has a performance cost even when the trace is not being recorded.  Defining
 * ATRACE_TAG to be ATRACE_TAG_NEVER or leaving ATRACE_TAG undefined will result
 * in the tracing always being disabled.
 *
 * ATRACE_TAG_HAL should be bitwise ORed with the relevant tags for tracing
 * within a hardware module.  For example a camera hardware module would set:
 * #define ATRACE_TAG  (ATRACE_TAG_CAMERA | ATRACE_TAG_HAL)
 *
 * Keep these in sync with frameworks/base/core/java/android/os/Trace.java.
 */
#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_PACKAGE_MANAGER  (1<<18)
#define ATRACE_TAG_SYSTEM_SERVER    (1<<19)
#define ATRACE_TAG_DATABASE         (1<<20)
#define ATRACE_TAG_NETWORK          (1<<21)
#define ATRACE_TAG_ADB              (1<<22)
#define ATRACE_TAG_VIBRATOR         (1<<23)
#define ATRACE_TAG_AIDL             (1<<24)
#define ATRACE_TAG_NNAPI            (1<<25)
#define ATRACE_TAG_RRO              (1<<26)
#define ATRACE_TAG_THERMAL          (1 << 27)
#define ATRACE_TAG_LAST             ATRACE_TAG_THERMAL

// Reserved for initialization.
#define ATRACE_TAG_NOT_READY        (1ULL<<63)

#define ATRACE_TAG_VALID_MASK ((ATRACE_TAG_LAST - 1) | ATRACE_TAG_LAST)

#ifndef ATRACE_TAG
#define ATRACE_TAG ATRACE_TAG_NEVER
#elif ATRACE_TAG > ATRACE_TAG_VALID_MASK
#error ATRACE_TAG must be defined to be one of the tags defined in cutils/trace.h
#endif

/**
 * Opens the trace file for writing and reads the property for initial tags.
 * The atrace.tags.enableflags property sets the tags to trace.
 * This function should not be explicitly called, the first call to any normal
 * trace function will cause it to be run safely.
 */
void atrace_setup();

/**
 * If tracing is ready, set atrace_enabled_tags to the system property
 * debug.atrace.tags.enableflags. Can be used as a sysprop change callback.
 */
void atrace_update_tags();

/**
 * Set whether tracing is enabled for the current process.  This is used to
 * prevent tracing within the Zygote process.
 */
void atrace_set_tracing_enabled(bool enabled);

/**
 * This is always set to false. This forces code that uses an old version
 * of this header to always call into atrace_setup, in which we call
 * atrace_init unconditionally.
 */
extern atomic_bool atrace_is_ready;

/**
 * Set of ATRACE_TAG flags to trace for, initialized to ATRACE_TAG_NOT_READY.
 * A value of zero indicates setup has failed.
 * Any other nonzero value indicates setup has succeeded, and tracing is on.
 */
extern uint64_t atrace_enabled_tags;

/**
 * Handle to the kernel's trace buffer, initialized to -1.
 * Any other value indicates setup has succeeded, and is a valid fd for tracing.
 */
extern int atrace_marker_fd;

/**
 * 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()
#define ATRACE_GET_ENABLED_TAGS() atrace_get_enabled_tags()

void atrace_init();
uint64_t atrace_get_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;
}

/**
 * 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))) {
        void atrace_begin_body(const char*);
        atrace_begin_body(name);
    }
}

/**
 * Trace the end of a context.
 * This should match up (and occur after) a corresponding ATRACE_BEGIN.
 */
#define ATRACE_END() atrace_end(ATRACE_TAG)
static inline void atrace_end(uint64_t tag)
{
    if (CC_UNLIKELY(atrace_is_tag_enabled(tag))) {
        void atrace_end_body();
        atrace_end_body();
    }
}

/**
 * Trace the beginning of an asynchronous event. Unlike ATRACE_BEGIN/ATRACE_END
 * contexts, asynchronous events do not need to be nested. The name describes
 * the event, and the cookie provides a unique identifier for distinguishing
 * simultaneous events. The name and cookie used to begin an event must be
 * used to end it.
 */
#define ATRACE_ASYNC_BEGIN(name, cookie) \
    atrace_async_begin(ATRACE_TAG, name, cookie)
static inline void atrace_async_begin(uint64_t tag, const char* name,
        int32_t cookie)
{
    if (CC_UNLIKELY(atrace_is_tag_enabled(tag))) {
        void atrace_async_begin_body(const char*, int32_t);
        atrace_async_begin_body(name, cookie);
    }
}

/**
 * Trace the end of an asynchronous event.
 * This should have a corresponding ATRACE_ASYNC_BEGIN.
 */
#define ATRACE_ASYNC_END(name, cookie) atrace_async_end(ATRACE_TAG, name, cookie)
static inline void atrace_async_end(uint64_t tag, const char* name, int32_t cookie)
{
    if (CC_UNLIKELY(atrace_is_tag_enabled(tag))) {
        void atrace_async_end_body(const char*, int32_t);
        atrace_async_end_body(name, cookie);
    }
}

/**
 * Trace the beginning of an asynchronous event. In addition to the name and a
 * cookie as in ATRACE_ASYNC_BEGIN/ATRACE_ASYNC_END, a track name argument is
 * provided, which is the name of the row where this async event should be
 * recorded. The track name, name, and cookie used to begin an event must be
 * used to end it.
 */
#define ATRACE_ASYNC_FOR_TRACK_BEGIN(track_name, name, cookie) \
    atrace_async_for_track_begin(ATRACE_TAG, track_name, name, cookie)
static inline void atrace_async_for_track_begin(uint64_t tag, const char* track_name,
                                                const char* name, int32_t cookie) {
    if (CC_UNLIKELY(atrace_is_tag_enabled(tag))) {
        void atrace_async_for_track_begin_body(const char*, const char*, int32_t);
        atrace_async_for_track_begin_body(track_name, name, cookie);
    }
}

/**
 * Trace the end of an asynchronous event.
 * This should correspond to a previous ATRACE_ASYNC_FOR_TRACK_BEGIN.
 */
#define ATRACE_ASYNC_FOR_TRACK_END(track_name, name, cookie) \
    atrace_async_for_track_end(ATRACE_TAG, track_name, name, cookie)
static inline void atrace_async_for_track_end(uint64_t tag, const char* track_name,
                                              const char* name, int32_t cookie) {
    if (CC_UNLIKELY(atrace_is_tag_enabled(tag))) {
        void atrace_async_for_track_end_body(const char*, const char*, int32_t);
        atrace_async_for_track_end_body(track_name, name, cookie);
    }
}

/**
 * Trace an instantaneous context. name is used to identify the context.
 *
 * An "instant" is an event with no defined duration. Visually is displayed like a single marker
 * in the timeline (rather than a span, in the case of begin/end events).
 *
 * By default, instant events are added into a dedicated track that has the same name of the event.
 * Use atrace_instant_for_track to put different instant events into the same timeline track/row.
 */
#define ATRACE_INSTANT(name) atrace_instant(ATRACE_TAG, name)
static inline void atrace_instant(uint64_t tag, const char* name) {
    if (CC_UNLIKELY(atrace_is_tag_enabled(tag))) {
        void atrace_instant_body(const char*);
        atrace_instant_body(name);
    }
}

/**
 * Trace an instantaneous context. name is used to identify the context.
 * track_name is the name of the row where the event should be recorded.
 *
 * An "instant" is an event with no defined duration. Visually is displayed like a single marker
 * in the timeline (rather than a span, in the case of begin/end events).
 */
#define ATRACE_INSTANT_FOR_TRACK(trackName, name) \
    atrace_instant_for_track(ATRACE_TAG, trackName, name)
static inline void atrace_instant_for_track(uint64_t tag, const char* track_name,
                                            const char* name) {
    if (CC_UNLIKELY(atrace_is_tag_enabled(tag))) {
        void atrace_instant_for_track_body(const char*, const char*);
        atrace_instant_for_track_body(track_name, name);
    }
}

/**
 * Traces an integer counter value.  name is used to identify the counter.
 * This can be used to track how a value changes over time.
 */
#define ATRACE_INT(name, value) atrace_int(ATRACE_TAG, name, value)
static inline void atrace_int(uint64_t tag, const char* name, int32_t value)
{
    if (CC_UNLIKELY(atrace_is_tag_enabled(tag))) {
        void atrace_int_body(const char*, int32_t);
        atrace_int_body(name, value);
    }
}

/**
 * Traces a 64-bit integer counter value.  name is used to identify the
 * counter. This can be used to track how a value changes over time.
 */
#define ATRACE_INT64(name, value) atrace_int64(ATRACE_TAG, name, value)
static inline void atrace_int64(uint64_t tag, const char* name, int64_t value)
{
    if (CC_UNLIKELY(atrace_is_tag_enabled(tag))) {
        void atrace_int64_body(const char*, int64_t);
        atrace_int64_body(name, value);
    }
}

__END_DECLS

#endif // _LIBS_CUTILS_TRACE_H

日常使用trace打TAG其实本质上都是基于这个类的,在这个的基础上会加一些额外包装

比如常见的几个方法:
1、ATRACE_CALL();

这个方法,代表对一个function的开头和结尾进行tag,它的源码如下

#define ATRACE_CALL() ATRACE_NAME(FUNCTION )

即本质调用的是ATRACE_NAME

调用如下:

2、ATRACE_NAME方法

这个方法的本质定义如下

cpp 复制代码
//这里的ATRACE_NAME其实本质是个临时对象构造和析构进行调用的atrace_begin和atrace_end,这两个其实就是trace.h原始方法
#define ATRACE_NAME(name) ::android::ScopedTrace PASTE(___tracer, __LINE__)(ATRACE_TAG, name)
namespace android {
//临时对象,调用该时候该对象刚好构造,一般方法域结束就代表作用无效了,因为会进行对象的析构
class ScopedTrace {
public:
    inline ScopedTrace(uint64_t tag, const char* name) : mTag(tag) {
        atrace_begin(mTag, name);//构造时候进行begin
            }

    inline ~ScopedTrace() {
        atrace_end(mTag);//析构时候代表trace结束end
    }

private:
    uint64_t mTag;
};

调用如下:

效果如下:

其他常见还有
3、ATRACE_INT

具体源码:

cpp 复制代码
/**
 * Traces an integer counter value.  name is used to identify the counter.
 * This can be used to track how a value changes over time.
 */
#define ATRACE_INT(name, value) atrace_int(ATRACE_TAG, name, value)
static inline void atrace_int(uint64_t tag, const char* name, int32_t value)
{
    if (CC_UNLIKELY(atrace_is_tag_enabled(tag))) {
        void atrace_int_body(const char*, int32_t);
        atrace_int_body(name, value);
    }
}

代码调用:

效果如下:

trace相关实战使用:

1、引入相关的头文件及相关库

#include <utils/Trace.h>

编译时候还得考率相关utils的lib是否引入

如这里以截图代码为例就有引入libutils

frameworks/base/cmds/screencap/Android.bp

cpp 复制代码
cc_binary {
    name: "screencap",

    srcs: ["screencap.cpp"],

    shared_libs: [
        "libcutils",
        "libutils",
        "libbinder",
        "libjnigraphics",
        "libui",
        "libgui",
    ],

    cflags: [
        "-Wall",
        "-Werror",
        "-Wunused",
        "-Wunreachable-code",
    ],
}

2、定义好相关的TAG

cpp 复制代码
 #undef ATRACE_TAG
#define ATRACE_TAG ATRACE_TAG_GRAPHICS

这里就选了一个ATRACE_TAG_GRAPHICS即graphics这个组

3、调用相关actrace方法

ATRACE_CALL

ATRACE_NAME

一般针对整个方法或者单独作用域,ATRACE_CALL和ATRACE_NAME本质没有区别,只是把名字变成了function的name
具体效果如下:
优点:只需要一个调用既可以实现tag打印,自动跟随作用域进行tag的结束

缺点:需要自己熟练掌握好作用域,没有可以手动控制的tag结束的点

4、相关灵活控制开始与结束的trace方法

直接使用atrace_begin和atrace_end方法,使用如下:

c 复制代码
GraphicBuffer::GraphicBuffer()
    : BASE(), mOwner(ownData), mBufferMapper(GraphicBufferMapper::get()),
      mInitCheck(NO_ERROR), mId(getUniqueId()), mGenerationNumber(0)
{
    ATRACE_NAME("GraphicBuffer::GraphicBuffer()1");
    atrace_begin(ATRACE_TAG, "GraphicBuffer 1");
    width  =
    height =
    stride =
    format =
    usage_deprecated = 0;
    atrace_end(ATRACE_TAG);
    usage  = 0;
    layerCount = 0;
    handle = nullptr;
}

具体效果如下:

同时也可以使用对应宏定义:

ATRACE_BEGIN(name);

ATRACE_END();

来控制

执行后效果如下:

更多framework干货手把手教学视频及答疑可以看这里,可以加我v(androidframework007)获取:

https://blog.csdn.net/learnframework/article/details/132739059

相关推荐
工业甲酰苯胺4 小时前
Redis性能优化的18招
数据库·redis·性能优化
无尽的大道9 小时前
深入理解 Java 阻塞队列:使用场景、原理与性能优化
java·开发语言·性能优化
loey_ln10 小时前
webpack配置和打包性能优化
前端·webpack·性能优化
郭梧悠21 小时前
HarmonyOS(57) UI性能优化
ui·性能优化·harmonyos
奈斯ing21 小时前
【Oracle篇】SQL性能优化实战案例(从15秒优化到0.08秒)(第七篇,总共七篇)
运维·数据库·sql·oracle·性能优化
青云交2 天前
大数据新视界 -- Impala 性能优化:分布式环境中的优化新视野(下)(28 / 30)
大数据·性能优化·资源管理·impala·优化策略·分布式环境·数据布局
hummhumm2 天前
第 24 章 -Golang 性能优化
java·开发语言·前端·后端·python·性能优化·golang
白茶等风121382 天前
准备阶段 Profiler性能分析工具的使用(一)
unity·性能优化
激流丶2 天前
【Redis 探秘】Redis 性能优化技巧
redis·性能优化·bootstrap