---
title: 高性能程序追踪库使用示例
description: "简要示范全流程使用高性能程序追踪库，整体流程如图1所示。"
url: https://www.hikunpeng.com/document/detail/zh/kunpengdevps/development/tracer/KunpengDevKitCli_0118.html
sourcePath: /source/zh/kunpengdevps/development/tracer/KunpengDevKitCli_0118.html
indexId: 18b30fada62a057752d68ef5da12ecb87bc4982889a39da1e290d86793e9843a69
---
# 高性能程序追踪库使用示例

简要示范全流程使用高性能程序追踪库，整体流程如图1所示。

图1 整体流程

文件目录结构：

```
/home/tracelog/ 
├── user.ini
├── user_demo.c  
├── logger_device
│   ├── lib 
│       ├──libkperf.so              #性能采集库，提供性能采集能力
│       ├──libloggerdevice.so       #功能库（动态库），提供日志序列化，反序列化能力
│       └──libsym.so                #符号解析库，提供符号解析能力  
│   ├── include
│       ├──dev_trace_log.h          #提供可直接调用的高性能程序追踪库的API
│       ├──dev_trace_log.metadata   #提供与dev_trace_log.h相对应的metadata解析文件
│       ├──logger_device.h          #对外接口头文件，提供序列化、反序列化相关接口
│       └──user.h
│   ├── bin                          
│       ├──tracelog                 #tracelog命令行，提供根据.ini文件生成对应头文件及解析日志文件的功能
│       └──example.ini              #生成代码功能输入.ini文件模板，用于配置日志
│   ├── 软件许可协议.txt
│   ├── README.md                   #tracelog命令行工具文档
│   └── Software License Agreement.txt
```


#### 生成代码使用示例

1. 工具包解压后，需配置环境变量。
  1 2 cd /home/tracelog/bin #在该路径下解压工具包 export LD_LIBRARY_PATH=/home/tracelog/logger_device/lib:$LD_LIBRARY_PATH

2. 以“/home/tracelog/user.ini”配置文件为例进行生成代码操作，在-o参数指定的路径下生成对应的user.h头文件。
  1 ./tracelog generator -i /home/tracelog/user.ini -o /home/tracelog/logger_device/include

  返回信息如下：

  1 [INFO] The basic code has been generated to /home/tracelog/logger_device/include/user.h.

  user.ini文件内容：

  1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 memoryKBs=5120 tracelog="/var/log/trace.log" [normal_example] name=char* id=int character=char [callstack_example] key=int callstack=3 [pmu_example] key=int enablepmu=true

  metadata文件和头文件会同时生成到同一目录下。

3. 查看生成的头文件。
  1 vim /home/tracelog/logger_device/include/user.h

  生成的对应头文件user.h内容：

  1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 #ifndef USER_H #define USER_H #include <stdlib.h> #include <stdio.h> #include <string.h> #include <stdbool.h> #include "logger_device.h" #define dev_tracepoint(module,event,...) dev_tracepoint_##module##_##event(__VA_ARGS__) #define MEMORY_KILOBYTES 5120 #define TRACELOG_FILENAME "/var/log/trace.log" static inline __attribute__((always_inline)) int ConvertToCTFStr(DataStream *pDataStream, const char *str, size_t strLen) { char *buffer = (char *)pDataStream->log + pDataStream->consumeSize; memcpy(buffer, str, strLen); pDataStream->consumeSize += strLen; return 0; } static inline __attribute__((always_inline)) int ConvertToCTFChar(DataStream *pDataStream, char c) { char *buffer = (char *)pDataStream->log + pDataStream->consumeSize; *buffer = c; pDataStream->consumeSize += 1; return 0; } static inline __attribute__((always_inline)) int ConvertToCTFInt(DataStream *pDataStream, int i) { int *buffer = (int *)((char *)pDataStream->log + pDataStream->consumeSize); *buffer = i; pDataStream->consumeSize += sizeof(int); return 0; } static inline __attribute__((always_inline)) int GetStrLenLineNum(int lineNum) { int len = 1; int i = lineNum; while (i >= 10) { ++len; i = i / 10; } return len; } static int dev_tracepoint_user_normal_example(const char *name, int id, char character) { int ret = InitLoggerDevice(TRACELOG_FILENAME, MEMORY_KILOBYTES, 1, NULL); if (ret != 0) { return ret; } size_t strLen_1 = strlen(name) + 1; size_t bodyLength = strLen_1 + 4 + 1; if (bodyLength > LOG_LENGTH) { return ERROR_LOG_TOO_LONG_FAIL; } size_t totalLength = (bodyLength + 40) * 8; DataStream dataStream = {0xC1FC1FC1, 0, totalLength, totalLength, 0, 0, {0}, 0}; ConvertToCTFStr(&dataStream, name, strLen_1); ConvertToCTFInt(&dataStream, id); ConvertToCTFChar(&dataStream, character); return LoggerDeviceWriter(1, &dataStream); } static int dev_tracepoint_user_callstack_example_callstack(int key) { int ret = InitLoggerDevice(TRACELOG_FILENAME, MEMORY_KILOBYTES, 1, NULL); if (ret != 0) { return ret; } CallStackResult cr = Backtrace(3); size_t bodyLength = 4; bodyLength += sizeof(cr); if (bodyLength > LOG_LENGTH) { return ERROR_LOG_TOO_LONG_FAIL; } size_t totalLength = (bodyLength + 40) * 8; DataStream dataStream = {0xC1FC1FC1, 1, totalLength, totalLength, 0, 0, {0}, 0}; memcpy(dataStream.log + bodyLength - sizeof(cr), &cr, sizeof(cr)); ConvertToCTFInt(&dataStream, key); return LoggerDeviceWriter(1, &dataStream); } static int dev_tracepoint_user_callstack_example(int key) { int ret = InitLoggerDevice(TRACELOG_FILENAME, MEMORY_KILOBYTES, 1, NULL); if (ret != 0) { return ret; } size_t bodyLength = 4; if (bodyLength > LOG_LENGTH) { return ERROR_LOG_TOO_LONG_FAIL; } size_t totalLength = (bodyLength + 40) * 8; DataStream dataStream = {0xC1FC1FC1, 2, totalLength, totalLength, 0, 0, {0}, 0}; ConvertToCTFInt(&dataStream, key); return LoggerDeviceWriter(1, &dataStream); } static int dev_tracepoint_user_pmu_example_enablepmu(int key) { int ret = InitLoggerDevice(TRACELOG_FILENAME, MEMORY_KILOBYTES, 1, NULL); if (ret != 0) { return ret; } PmuResult pmuData = GetPmuData(); size_t bodyLength = 4; bodyLength += sizeof(pmuData); if (bodyLength > LOG_LENGTH) { return ERROR_LOG_TOO_LONG_FAIL; } size_t totalLength = (bodyLength + 40) * 8; DataStream dataStream = {0xC1FC1FC1, 3, totalLength, totalLength, 0, 0, {0}, 0}; memcpy(dataStream.log + bodyLength - sizeof(pmuData), &pmuData, sizeof(pmuData)); ConvertToCTFInt(&dataStream, key); return LoggerDeviceWriter(1, &dataStream); } static int dev_tracepoint_user_pmu_example(int key) { int ret = InitLoggerDevice(TRACELOG_FILENAME, MEMORY_KILOBYTES, 1, NULL); if (ret != 0) { return ret; } size_t bodyLength = 4; if (bodyLength > LOG_LENGTH) { return ERROR_LOG_TOO_LONG_FAIL; } size_t totalLength = (bodyLength + 40) * 8; DataStream dataStream = {0xC1FC1FC1, 4, totalLength, totalLength, 0, 0, {0}, 0}; ConvertToCTFInt(&dataStream, key); return LoggerDeviceWriter(1, &dataStream); } #endif

4. 重新指定追踪库使用缓存大小，可以在user.h头文件中修改宏定义MEMORY_KILOBYTES的值。
  1 #define MEMORY_KILOBYTES 6120

5. 重新指定trace.log文件和ProcMaps文件的路径，可以在user.h头文件中修改宏定义TRACELOG_FILENAME的值。
  1 #define TRACELOG_FILENAME "/home/tracelog/custom.log"


#### 功能库使用示例

1. 请提前准备demo文件，demo文件中已引用生成的user.h文件。
查看“/home/tracelog/user_demo.c”文件。```
vim /home/tracelog/user_demo.c
```


文件内容如下：
```
#include <stdio.h>
#include "user.h"
int main(){
    dev_tracepoint(user, normal_example, "hello", 18, 'a');
    dev_tracepoint(user, callstack_example_callstack, 4);  //调用了会记录调用栈数据的接口
    dev_tracepoint(user, pmu_example_enablepmu, 5);  //调用了会记录PMU数据的接口
    DestroyLoggerDevice();
}
```


  - dev_tracepoint(user, normal_example, "hello", 18, 'a')：按照.ini配置文件中定义的参数类型顺序来调用dev_tracepoint接口，即日志接口。
  - dev_tracepoint(user, callstack_example_callstack, 4)：此处调用callstack类型的日志接口。
  - dev_tracepoint(user, pmu_example_enablepmu, 5)：此处调用PMU类型的日志接口。
  - DestroyLoggerDevice()：在业务应用运行结束前，结束使用功能库。
2. 编译user_demo.c。
  1 gcc /home/tracelog/user_demo.c -I /home/tracelog/logger_device/include/ -l loggerdevice -L /home/tracelog/logger_device/lib -o /home/tracelog/user_demo -g -O0

  -I（大写i）：头文件所在路径。 -l（小写L）：功能库名称。 -L：功能库所在路径。 -o：生成的二进制文件。

3. 将loggerdevice库的所在路径加到LD_LIBRARY_PATH环境变量。
  1 export LD_LIBRARY_PATH=/home/tracelog/logger_device/lib:$LD_LIBRARY_PATH

4. 运行user_demo。
  1 /home/tracelog/user_demo

  运行完成后会在user.h中指定的路径“/home/tracelog/”下生成custom.log1740206079754882文件和ProcMaps文件。 在生成的头文件中，用户可通过修改宏定义内容指定日志文件生成路径，日志文件名带有时间戳，不会覆盖系统文件。日志文件中打印的内容均为用户的业务日志，不打印高性能程序追踪库本身的日志，文件权限为600。每个日志文件大小在100MB以内，且无日志注入风险。 “/home/tracelog/”：生成的日志文件路径。 custom.log1740206079754882：日志文件名称。 ProcMaps：内存映射信息文件，ProcMaps文件与日志文件会生成到同一目录下。


#### 日志解析使用示例

1. 以用户在user_demo.c中调用dev_tracepoint接口为例，在编译并执行相应的业务应用后会在“/home/tracelog/”下生成对应custom.log1740467391374218文件和ProcMaps文件。
  dev_tracepoint接口信息如下：

```
dev_tracepoint(user, normal_example, "hello", 18, 'a');
dev_tracepoint(user, callstack_example, 4);
dev_tracepoint(user, pmu_example, 5);
```


2. 执行日志解析命令。
  1 2 cd /home/tracelog/bin ./tracelog parser -md /home/tracelog/logger_device/include/metadata -tl /home/tracelog/custom.log1740467391374218 -mf /home/tracelog/ProcMaps

  返回信息如下：

  1 2 3 4 5 6 7 8 9 10 [2025-05-15 16:06:29] str1 = "hello", i1 = 18, c1 = a [2025-05-15 16:06:29] i1 = 4, callstack = "Thread ID: 2533516 Frame #00: [0x400bd0] dev_tracepoint_user_callstack_example at /home/tracelog/logger_device/include/user.h:69 Frame #01: [0x400e18] main at /home/tracelog/user_demo.c:5 Frame #02: [0xffff8059763c] UNKNOWN at (null):0 " [2025-05-15 16:06:29] i1 = 5, Pmudata: tid = 2533320 cycles = 0
