├── .gitingnore
├── README.md
├── README_zh.md
├── example
├── Makefile
├── README.md
├── README_zh.md
└── main.cpp
└── tracer.h
/.gitingnore:
--------------------------------------------------------------------------------
1 | *.o
2 | example/tracer_example
3 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Tracer - Lightweight Performance Tracing Library
2 |
3 | [](README.md)
4 | [](README_zh.md)
5 |
6 | Tracer is a header-only lightweight performance tracing library for recording and analyzing C++ program execution. It helps developers identify performance bottlenecks, analyze function execution times, and outputs results in Chrome Tracing compatible format for easy visualization.
7 |
8 | ## Features
9 |
10 | - **Easy Integration**: Just include a single header file
11 | - **Low Overhead**: Designed to minimize impact on the analyzed program
12 | - **Visualization Friendly**: Generates Chrome Tracing compatible JSON output
13 | - **Thread-Safe**: Supports multi-threaded application analysis
14 | - **Automatic Management**: Uses RAII-style C++ objects for automatic scope tracing
15 | - **Optional Compilation**: Can be completely disabled at compile time via macro definition
16 |
17 | ## Quick Start
18 |
19 | 1. Copy the `tracer.h` file to your project
20 | 2. Include the header in source files you want to trace:
21 | ```cpp
22 | #include "tracer/tracer.h"
23 | ```
24 | 3. Use the provided macros to trace code execution:
25 |
26 | ```cpp
27 | void some_function() {
28 | TRACE_SCOPE("some_function"); // Automatically traces function scope
29 |
30 | // Function code...
31 |
32 | TRACE_INSTANT("interesting_point"); // Records an instant event
33 |
34 | // More code...
35 | }
36 | ```
37 |
38 | 4. Save trace results at the end of your program:
39 | ```cpp
40 | TRACE_SAVE("trace_result.json");
41 | ```
42 | 5. View results in Chrome browser:
43 | - Open Chrome
44 | - Visit `chrome://tracing`
45 | - Click "Load" button to load the generated JSON file
46 |
47 | ## API Documentation
48 |
49 | ### Macros
50 |
51 | - `TRACE_SCOPE(name)`: Creates a scope event that automatically records entry and exit times
52 | - `TRACE_INSTANT(name)`: Records an instant event
53 | - `TRACE_DATA(p_str)`: Gets collected trace data and saves to the specified string pointer
54 | - `TRACE_SAVE(filename)`: Saves trace data to a file
55 |
56 | ### Disabling Tracing
57 |
58 | Define the `TRACE_DISABLED` macro to disable all tracing code at compile time:
59 |
60 | ```cpp
61 | #define TRACE_DISABLED
62 | #include "tracer/tracer.h"
63 | ```
64 |
65 | Or add to your compile command:
66 |
67 | ```bash
68 | g++ -DTRACE_DISABLED ...
69 | ```
70 |
71 | ## Examples
72 |
73 | Check out the example program in the `example` directory to see how to use Tracer in a real project:
74 |
75 | ```bash
76 | cd example
77 | make
78 | ./tracer_example
79 | ```
80 |
81 | The `trace_result.json` file generated by the example program can be directly opened in Chrome's tracing page.
82 |
83 | ## Performance Considerations
84 |
85 | - Tracer uses a ring buffer to store events, with a default capacity of 10,000 events
86 | - When capacity is reached, new events overwrite the oldest ones
87 | - Each event includes name, timestamp, duration, thread ID, process ID, and CPU usage information
88 | - Efficient multi-threading support is implemented via thread-local storage
89 |
90 | ## License
91 |
92 | This project is released under the MIT License. See the LICENSE file for details.
93 |
94 | ## Contributing
95 |
96 | Feedback and improvements are welcome via Issues and Pull Requests.
97 |
--------------------------------------------------------------------------------
/README_zh.md:
--------------------------------------------------------------------------------
1 | # Tracer - 轻量级性能跟踪库
2 |
3 | [](README.md)
4 | [](README_zh.md)
5 |
6 | Tracer 是一个头文件级的轻量级性能跟踪库,用于记录和分析 C++ 程序的执行性能。它可以帮助开发者识别性能瓶颈、分析函数执行时间,并以兼容 Chrome Tracing 格式输出结果,便于可视化分析。
7 |
8 | ## 特性
9 |
10 | - **易于集成**:仅需包含单个头文件
11 | - **低开销**:设计为最小化对被分析程序的影响
12 | - **可视化友好**:生成 Chrome Tracing 兼容的 JSON 格式输出
13 | - **线程安全**:支持多线程应用程序分析
14 | - **自动管理**:使用 RAII 风格的 C++ 对象自动管理作用域跟踪
15 | - **可选编译**:可通过宏定义在编译时完全禁用
16 |
17 | ## 快速开始
18 |
19 | 1. 将 `tracer.h` 文件复制到您的项目中
20 | 2. 在需要跟踪的源文件中包含头文件:
21 | ```cpp
22 | #include "tracer/tracer.h"
23 | ```
24 | 3. 使用提供的宏跟踪代码执行:
25 |
26 | ```cpp
27 | void some_function() {
28 | TRACE_SCOPE("some_function"); // 自动跟踪函数作用域
29 |
30 | // 函数执行代码...
31 |
32 | TRACE_INSTANT("interesting_point"); // 记录即时事件
33 |
34 | // 更多代码...
35 | }
36 | ```
37 |
38 | 4. 程序结束时保存跟踪结果:
39 | ```cpp
40 | TRACE_SAVE("trace_result.json");
41 | ```
42 | 5. 在 Chrome 浏览器中查看结果:
43 | - 打开 Chrome
44 | - 访问 `chrome://tracing`
45 | - 点击 "Load" 按钮加载生成的 JSON 文件
46 |
47 | ## API 文档
48 |
49 | ### 宏定义
50 |
51 | - `TRACE_SCOPE(name)`:创建一个作用域事件,自动记录进入和退出时间
52 | - `TRACE_INSTANT(name)`:记录一个即时事件
53 | - `TRACE_DATA(p_str)`:获取已收集的跟踪数据并保存到指定字符串指针
54 | - `TRACE_SAVE(filename)`:将跟踪数据保存到文件
55 |
56 | ### 禁用跟踪
57 |
58 | 定义 `TRACE_DISABLED` 宏可以在编译时禁用所有跟踪代码:
59 |
60 | ```cpp
61 | #define TRACE_DISABLED
62 | #include "tracer/tracer.h"
63 | ```
64 |
65 | 或在编译命令中添加:
66 |
67 | ```bash
68 | g++ -DTRACE_DISABLED ...
69 | ```
70 |
71 | ## 示例
72 |
73 | 查看 `example` 目录中的示例程序,了解如何在实际项目中使用 Tracer:
74 |
75 | ```bash
76 | cd example
77 | make
78 | ./tracer_example
79 | ```
80 |
81 | 示例程序生成的 `trace_result.json` 文件可以直接在 Chrome 的 tracing 页面中打开查看。
82 |
83 | ## 性能考虑
84 |
85 | - Tracer 使用环形缓冲区存储事件,默认容量为 10,000 个事件
86 | - 达到容量上限后,新事件会覆盖最旧的事件
87 | - 每个事件包含名称、时间戳、持续时间、线程 ID、进程 ID 和 CPU 使用信息
88 | - 通过线程本地存储实现高效的多线程支持
89 |
90 | ## 许可
91 |
92 | 本项目采用 MIT 许可证发布,详情请查看 LICENSE 文件。
93 |
94 | ## 贡献
95 |
96 | 欢迎通过 Issue 和 Pull Request 提供反馈和改进。
97 |
--------------------------------------------------------------------------------
/example/Makefile:
--------------------------------------------------------------------------------
1 | CC := g++
2 | CFLAGS := -std=c++11 -Wall -Wextra -pthread
3 |
4 | # 目标可执行文件
5 | TARGET := tracer_example
6 |
7 | # 源文件
8 | SRCS := main.cpp
9 |
10 | # 头文件路径
11 | INCLUDES := -I..
12 |
13 | # 目标文件
14 | OBJS := $(SRCS:.cpp=.o)
15 |
16 | # 默认目标
17 | all: $(TARGET)
18 |
19 | # 编译规则
20 | $(TARGET): $(OBJS)
21 | $(CC) $(CFLAGS) -o $@ $^
22 |
23 | # 编译源文件
24 | %.o: %.cpp
25 | $(CC) $(CFLAGS) $(INCLUDES) -c $< -o $@
26 |
27 | # 禁用跟踪的编译选项
28 | disable_trace: CFLAGS += -DTRACE_DISABLED
29 | disable_trace: clean $(TARGET)
30 |
31 | # 清理生成的文件
32 | clean:
33 | rm -f $(OBJS) $(TARGET) trace_result.json
34 |
35 | # 运行示例
36 | run: $(TARGET)
37 | ./$(TARGET)
38 |
39 | # 查看跟踪结果
40 | view: run
41 | @echo "Trace file generated: trace_result.json"
42 | @echo "Please open chrome://tracing in your browser and load the file to view results"
43 |
44 | .PHONY: all clean run view disable_trace
45 |
--------------------------------------------------------------------------------
/example/README.md:
--------------------------------------------------------------------------------
1 | # Tracer Example
2 |
3 | [English](#english) | [中文](#chinese)
4 |
5 |
6 |
7 | ## English
8 |
9 | # Tracer Example
10 |
11 | [](README.md)
12 | [](README_zh.md)
13 |
14 | This example demonstrates how to use the Tracer library to profile and analyze the performance of a multi-threaded application.
15 |
16 | ## Overview
17 |
18 | The example program creates multiple worker threads that perform a mix of compute-intensive and I/O-bound tasks. The Tracer library is used to record various events during execution, including:
19 |
20 | - Function entry/exit times
21 | - Instant events at specific points in the code
22 | - Thread names and IDs
23 | - CPU core usage
24 |
25 | ### Building the Example
26 |
27 | To build the example, use the provided Makefile:
28 |
29 | ```bash
30 | make
31 | ```
32 |
33 | ### Running the Example
34 |
35 | After building, run the example:
36 |
37 | ```bash
38 | ./tracer_example
39 | ```
40 |
41 | Alternatively, you can use the run target:
42 |
43 | ```bash
44 | make run
45 | ```
46 |
47 | The program will generate a trace file named `trace_result.json` in the current directory.
48 |
49 | ### Viewing the Results
50 |
51 | To view the trace results:
52 |
53 | 1. Open Google Chrome
54 | 2. Navigate to `chrome://tracing/`
55 | 3. Click "Load" and select the `trace_result.json` file
56 |
57 | You can also use the view target, which builds, runs and reminds you how to view the results:
58 |
59 | ```bash
60 | make view
61 | ```
62 |
63 | You'll see a timeline visualization of all the recorded events:
64 |
65 | - Each thread appears as a separate row
66 | - Function calls are shown as colored bars, with the width representing the duration
67 | - Instant events appear as vertical markers
68 | - Hover over events to see details like CPU core used and timing information
69 |
70 | ### Understanding the Output
71 |
72 | The visualization will help you identify:
73 |
74 | - Which functions take the most time
75 | - How work is distributed across threads
76 | - When CPU vs I/O bottlenecks occur
77 | - Thread synchronization issues
78 | - CPU core migration patterns
79 |
80 | ### Modifying the Example
81 |
82 | You can experiment with the example by:
83 |
84 | - Changing the number of worker threads
85 | - Adjusting the workload parameters
86 | - Adding more `TRACE_SCOPE` and `TRACE_INSTANT` markers
87 | - Enabling/disabling tracing with the `TRACE_DISABLED` macro (use `make disable_trace` to build with tracing disabled)
88 |
89 | ## Using Tracer in Your Own Projects
90 |
91 | To use Tracer in your own projects:
92 |
93 | 1. Copy the `tracer.h` file to your project
94 | 2. Include it in your source files: `#include "tracer.h"`
95 | 3. Add `TRACE_SCOPE()` calls around functions you want to profile
96 | 4. Use `TRACE_INSTANT()` for key events
97 | 5. Call `TRACE_SAVE()` to write results to a file
98 |
99 | ---
100 |
101 |
102 |
103 | ## 中文
104 |
105 | 本示例演示如何使用 Tracer 库来分析多线程应用程序的性能。
106 |
107 | ### 概述
108 |
109 | 示例程序创建多个工作线程,执行计算密集型和 I/O 密集型任务的组合。Tracer 库用于记录执行过程中的各种事件,包括:
110 |
111 | - 函数进入/退出时间
112 | - 代码中特定点的即时事件
113 | - 线程名称和 ID
114 | - CPU 核心使用情况
115 |
116 | ### 构建示例
117 |
118 | 使用提供的 Makefile 构建示例:
119 |
120 | ```bash
121 | make
122 | ```
123 |
124 | ### 运行示例
125 |
126 | 构建完成后,运行示例:
127 |
128 | ```bash
129 | ./tracer_example
130 | ```
131 |
132 | 或者,您可以使用 run 目标:
133 |
134 | ```bash
135 | make run
136 | ```
137 |
138 | 程序将在当前目录中生成名为 `trace_result.json`
139 |
--------------------------------------------------------------------------------
/example/README_zh.md:
--------------------------------------------------------------------------------
1 | # Tracer 示例程序
2 |
3 | [](README.md)
4 | [](README_zh.md)
5 |
6 | 本示例展示了如何使用 Tracer 库来分析多线程应用程序的性能。
7 |
8 | ## 概述
9 |
10 | 示例程序创建多个工作线程,执行计算密集型和 I/O 密集型任务的组合。Tracer 库用于记录执行过程中的各种事件,包括:
11 |
12 | - 函数进入/退出时间
13 | - 代码中特定点的即时事件
14 | - 线程名称和 ID
15 | - CPU 核心使用情况
16 |
17 | ## 构建示例
18 |
19 | 使用提供的 Makefile 构建示例:
20 |
21 | ```bash
22 | make
23 | ```
24 |
25 | ## 运行示例
26 |
27 | 构建后,运行示例程序:
28 |
29 | ```bash
30 | ./tracer_example
31 | ```
32 |
33 | 或者,你可以使用 run 目标:
34 |
35 | ```bash
36 | make run
37 | ```
38 |
39 | 程序将在当前目录中生成名为 `trace_result.json` 的跟踪文件。
40 |
41 | ## 查看结果
42 |
43 | 查看跟踪结果:
44 |
45 | 1. 打开 Google Chrome 浏览器
46 | 2. 访问 `chrome://tracing/`
47 | 3. 点击 "Load" 按钮并选择 `trace_result.json` 文件
48 |
49 | 你也可以使用 view 目标,它会构建、运行程序并提醒你如何查看结果:
50 |
51 | ```bash
52 | make view
53 | ```
54 |
55 | 你将看到所有记录事件的时间线可视化:
56 |
57 | - 每个线程显示为单独的一行
58 | - 函数调用显示为彩色条形,宽度表示持续时间
59 | - 即时事件显示为垂直标记
60 | - 鼠标悬停在事件上可查看详细信息,如使用的 CPU 核心和时间信息
61 |
62 | ## 理解输出
63 |
64 | 可视化将帮助你识别:
65 |
66 | - 哪些函数占用最多时间
67 | - 工作如何在线程间分配
68 | - CPU 与 I/O 瓶颈发生的时间
69 | - 线程同步问题
70 | - CPU 核心迁移模式
71 |
72 | ## 修改示例
73 |
74 | 你可以通过以下方式实验修改示例:
75 |
76 | - 改变工作线程数量
77 | - 调整工作负载参数
78 | - 添加更多 `TRACE_SCOPE` 和 `TRACE_INSTANT` 标记
79 | - 使用 `TRACE_DISABLED` 宏启用/禁用跟踪(使用 `make disable_trace` 构建时禁用跟踪)
80 |
81 | ## 在自己的项目中使用 Tracer
82 |
83 | 要在自己的项目中使用 Tracer:
84 |
85 | 1. 将 `tracer.h` 文件复制到你的项目中
86 | 2. 在源文件中包含它:`#include "tracer.h"`
87 | 3. 在你想要分析的函数周围添加 `TRACE_SCOPE()` 调用
88 | 4. 对关键事件使用 `TRACE_INSTANT()`
89 | 5. 调用 `TRACE_SAVE()` 将结果写入文件
90 |
--------------------------------------------------------------------------------
/example/main.cpp:
--------------------------------------------------------------------------------
1 | #include "../tracer.h"
2 | #include
3 | #include
4 | #include
5 | #include
6 | #include
7 | #include
8 |
9 | // 模拟一个计算密集型任务
10 | void compute_task(int iterations) {
11 | TRACE_SCOPE("compute_task");
12 |
13 | volatile double result = 0.0;
14 | for (int i = 0; i < iterations; ++i) {
15 | TRACE_SCOPE("compute_iteration");
16 |
17 | // 一些计算工作
18 | for (int j = 0; j < 1000000; ++j) {
19 | result += sin(j * 0.0001) * cos(j * 0.0001);
20 | }
21 |
22 | // 记录一个即时事件
23 | if (i % 5 == 0) {
24 | TRACE_INSTANT("iteration_milestone");
25 | }
26 |
27 | // 短暂休眠模拟 I/O 等待
28 | if (i % 3 == 0) {
29 | std::this_thread::sleep_for(std::chrono::milliseconds(10));
30 | }
31 | }
32 | }
33 |
34 | // 模拟一个 I/O 任务
35 | void io_task(int operations) {
36 | TRACE_SCOPE("io_task");
37 |
38 | for (int i = 0; i < operations; ++i) {
39 | TRACE_SCOPE("io_operation");
40 |
41 | // 模拟 I/O 操作的延迟
42 | std::this_thread::sleep_for(std::chrono::milliseconds(50));
43 |
44 | // 模拟处理 I/O 结果的一些计算
45 | volatile double result = 0.0;
46 | for (int j = 0; j < 100000; ++j) {
47 | result += sin(j * 0.001);
48 | }
49 | }
50 | }
51 |
52 | // 多线程工作函数
53 | void worker_thread(int id, int compute_iterations, int io_operations) {
54 | TRACE_SCOPE("worker_thread");
55 |
56 | // 设置线程名称
57 | char thread_name[32];
58 | snprintf(thread_name, sizeof(thread_name), "Worker-%d", id);
59 | pthread_setname_np(pthread_self(), thread_name);
60 |
61 | // 执行一些计算任务
62 | compute_task(compute_iterations);
63 |
64 | // 执行一些 I/O 任务
65 | io_task(io_operations);
66 | }
67 |
68 | int main() {
69 | TRACE_SCOPE("main");
70 |
71 | std::cout << "Tracer example program starting..." << std::endl;
72 |
73 | // 创建多个工作线程
74 | std::vector threads;
75 | const int num_threads = 4;
76 |
77 | for (int i = 0; i < num_threads; ++i) {
78 | // 每个线程执行不同工作量的任务
79 | int compute_iterations = 10 + i;
80 | int io_operations = 5 + (i % 3);
81 |
82 | threads.emplace_back(worker_thread, i, compute_iterations, io_operations);
83 |
84 | // 稍微错开线程启动时间
85 | std::this_thread::sleep_for(std::chrono::milliseconds(100));
86 | }
87 |
88 | // 主线程也做一些工作
89 | {
90 | TRACE_SCOPE("main_processing");
91 |
92 | // 主线程执行一些操作
93 | std::cout << "Main thread processing..." << std::endl;
94 | std::this_thread::sleep_for(std::chrono::milliseconds(500));
95 |
96 | // 添加一些即时事件
97 | TRACE_INSTANT("main_work_checkpoint");
98 | }
99 |
100 | // 等待所有线程完成
101 | for (auto &t : threads) {
102 | t.join();
103 | }
104 |
105 | // 保存跟踪结果到文件
106 | std::cout
107 | << "\nAll threads completed.\nSaving trace to 'trace_result.json'..."
108 | << std::endl;
109 | TRACE_SAVE("trace_result.json");
110 |
111 | std::cout << "Example completed. Open 'trace_result.json' in "
112 | "chrome://tracing to view results."
113 | << std::endl;
114 | return 0;
115 | }
116 |
--------------------------------------------------------------------------------
/tracer.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 |
5 | #include
6 | #include
7 | #include
8 | #include
9 | #include
10 | #include
11 | #include
12 | #include
13 |
14 | #ifdef TRACE_DISABLED
15 | #define TRACE_SCOPE(name)
16 | #define TRACE_INSTANT(name)
17 | #define TRACE_DATA(p_str)
18 | #define TRACE_SAVE(filename)
19 | #else
20 | #define TRACE_SCOPE(name) TraceScopeRAII __trace_scope_raii_##__LINE__(name)
21 | #define TRACE_INSTANT(name) Tracer::instance().recordInstant(name)
22 | #define TRACE_DATA(p_str) Tracer::instance().data(p_str)
23 | #define TRACE_SAVE(filename) Tracer::instance().save(filename)
24 | #endif
25 |
26 | class Tracer {
27 | public:
28 | struct KV {
29 | std::string name;
30 | std::string value;
31 | };
32 | struct Event {
33 | const char *name;
34 | const char *phase;
35 | uint64_t ts_us;
36 | uint64_t dur_us;
37 | uint32_t pid;
38 | uint32_t tid;
39 | uint32_t cpu[2];
40 | std::list args;
41 |
42 | std::string toJSON() const {
43 | std::string json;
44 | json.reserve(512);
45 | auto format_str = [](const char *fmt, ...) {
46 | char buffer[128] = {0};
47 | va_list args;
48 | va_start(args, fmt);
49 | vsnprintf(buffer, sizeof(buffer), fmt, args);
50 | va_end(args);
51 | return std::string(buffer);
52 | };
53 |
54 | json.append(
55 | format_str(R"({"name":"%s","cat":"function","ph":"%s","ts":%lu)",
56 | name, phase, ts_us));
57 | if (phase[0] == 'X') {
58 | json.append(format_str(R"(,"dur":%lu)", dur_us));
59 | }
60 | json.append(format_str(R"(,"pid":%u,"tid":%u)", pid, tid));
61 |
62 | // args
63 | std::string args_str;
64 | auto append = [&](const std::string &str) { args_str.append(str); };
65 | append("{");
66 | for (const auto &kv : args) {
67 | append(format_str(R"("%s":"%s",)", kv.name.c_str(), kv.value.c_str()));
68 | }
69 | append(format_str(R"("cpu": %d,)", cpu[0]));
70 | append(format_str(R"("cpu2": %d})", cpu[1]));
71 |
72 | if (!args_str.empty()) {
73 | json.append(format_str(R"(,"args":%s})", args_str.c_str()));
74 | } else {
75 | json.append("}");
76 | }
77 | return json;
78 | }
79 | };
80 |
81 | static constexpr size_t MAX_EVENTS = 1e4;
82 |
83 | Tracer() : write_index_(0) { events_ = new Event[MAX_EVENTS]; }
84 |
85 | ~Tracer() { delete[] events_; }
86 |
87 | static Tracer &instance() {
88 | static Tracer inst;
89 | return inst;
90 | }
91 |
92 | void recordInstant(const char *name) {
93 | registerThreadName();
94 | Event e{name, "i", now_us(), 0, pid(), tid(), {cpu(), 0}};
95 | pushEvent(e);
96 | }
97 |
98 | void begin(const char *name) {
99 | registerThreadName();
100 | uint64_t ts = now_us();
101 | ThreadLocalData &data = tls();
102 | data.stack.push_back({name, "X", ts, 0, pid(), tid(), {cpu(), 0}});
103 | }
104 |
105 | void end() {
106 | uint64_t ts = now_us();
107 | ThreadLocalData &data = tls();
108 | if (data.stack.empty())
109 | return;
110 | Event e = data.stack.back();
111 | data.stack.pop_back();
112 | e.dur_us = ts - e.ts_us;
113 | e.cpu[1] = cpu(); // end cpu
114 | pushEvent(e);
115 | }
116 |
117 | void data(std::string *out) {
118 | size_t snapshot = write_index_.load(std::memory_order_acquire);
119 | size_t count = full_ ? MAX_EVENTS : snapshot;
120 | size_t start = full_ ? snapshot % MAX_EVENTS : 0;
121 |
122 | out->clear();
123 | out->reserve(count * 512);
124 | auto append = [&](const std::string &str) { out->append(str); };
125 | append("{\"traceEvents\":[\n");
126 | for (size_t i = 0; i < count; ++i) {
127 | size_t idx = (start + i) % MAX_EVENTS;
128 | append(events_[idx].toJSON());
129 | if (i != count - 1)
130 | append(",");
131 | append("\n");
132 | }
133 | append("]}\n");
134 | }
135 |
136 | void save(const std::string &filename) {
137 | std::ofstream out(filename);
138 | std::string str;
139 | data(&str);
140 | out << str;
141 | out.close();
142 | }
143 | void registerThreadName() {
144 | ThreadLocalData &data = tls();
145 | if (data.thread_metadata_registered)
146 | return;
147 |
148 | data.thread_metadata_registered = true;
149 |
150 | uint32_t thread_id = tid();
151 | char name[32];
152 | pthread_getname_np(pthread_self(), name, sizeof(name));
153 | std::string thread_name(name);
154 | Event meta;
155 | meta.name = "thread_name";
156 | meta.phase = "M";
157 | meta.ts_us = 0;
158 | meta.dur_us = 0;
159 | meta.pid = pid();
160 | meta.tid = thread_id;
161 | meta.args.push_back({"name", thread_name});
162 |
163 | pushEvent(meta);
164 | }
165 |
166 | private:
167 | struct ThreadLocalData {
168 | std::vector stack;
169 | bool thread_metadata_registered = false;
170 | };
171 |
172 | static ThreadLocalData &tls() {
173 | thread_local ThreadLocalData data;
174 | return data;
175 | }
176 |
177 | uint64_t now_us() const {
178 | auto now = std::chrono::steady_clock::now();
179 | return std::chrono::duration_cast(
180 | now.time_since_epoch())
181 | .count();
182 | }
183 | uint32_t cpu() const { return static_cast(sched_getcpu()); }
184 | uint32_t tid() const { return gettid(); }
185 | uint32_t pid() const {
186 | static uint32_t cached_pid = static_cast(getpid());
187 | return cached_pid;
188 | }
189 | void pushEvent(const Event &e) {
190 | size_t idx = write_index_.fetch_add(1, std::memory_order_relaxed);
191 | if (idx >= MAX_EVENTS) {
192 | full_ = true;
193 | if (idx % MAX_EVENTS == 0) {
194 | tls().thread_metadata_registered = false;
195 | }
196 | }
197 | events_[idx % MAX_EVENTS] = e;
198 | }
199 |
200 | std::atomic write_index_;
201 | Event *events_;
202 | bool full_;
203 | };
204 |
205 | // RAII 范围事件
206 | class TraceScopeRAII {
207 | public:
208 | TraceScopeRAII(const char *name) { Tracer::instance().begin(name); }
209 | ~TraceScopeRAII() { Tracer::instance().end(); }
210 | };
211 |
--------------------------------------------------------------------------------