Tracy Profiler 是目前 C++ 多线程程序(游戏引擎、SLAM、视觉系统)里 最强的实时性能分析工具之一 。
它可以精确分析:
- 线程运行时间
- 线程等待时间
- mutex 锁竞争
- CPU cache miss
- frame pipeline
对于 统计线程等待其他线程数据时间 ,Tracy 的 Zone + Lock Profiling 非常适合。
一、基础示例:统计线程等待数据时间
1 引入 Tracy
下载:
https://github.com/wolfpld/tracy
项目中包含:
cpp
Tracy.hpp
TracyClient.cpp
编译时需要:
cpp
#define TRACY_ENABLE
2 示例代码
cpp
#include <thread>
#include <mutex>
#include <condition_variable>
#include <queue>
#define TRACY_ENABLE
#include "Tracy.hpp"
std::mutex mtx;
std::condition_variable cv;
std::queue<int> dataQueue;
bool running = true;
void producer()
{
while (running)
{
ZoneScoped; // Tracy 统计该函数执行时间
std::this_thread::sleep_for(std::chrono::milliseconds(30));
{
std::lock_guard<std::mutex> lock(mtx);
dataQueue.push(rand());
}
cv.notify_one();
}
}
void consumer()
{
while (running)
{
ZoneScoped;
std::unique_lock<std::mutex> lock(mtx);
ZoneScopedN("Waiting Data");
cv.wait(lock, [] { return !dataQueue.empty(); });
int value = dataQueue.front();
dataQueue.pop();
lock.unlock();
std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
}
int main()
{
tracy::SetThreadName("Main Thread");
std::thread t1(producer);
std::thread t2(consumer);
tracy::SetThreadName("Producer");
tracy::SetThreadName("Consumer");
std::this_thread::sleep_for(std::chrono::seconds(10));
running = false;
t1.join();
t2.join();
}
二、Tracy 显示效果
运行后打开:
Tracy.exe
可以看到 timeline:
Producer Thread
██████ compute
██████ compute
Consumer Thread
██ wait data
████ compute
██ wait data
你会看到:
Waiting Data
这段时间就是 线程等待数据时间。
三、精确统计 Mutex 等待时间
Tracy 还可以直接统计 锁竞争。
使用:
cpp
#include "TracyLock.hpp"
代码改为:
cpp
tracy::Lockable<std::mutex> mtx;
示例:
cpp
tracy::Lockable<std::mutex> mtx;
void consumer()
{
while (running)
{
ZoneScoped;
std::unique_lock<tracy::Lockable<std::mutex>> lock(mtx);
cv.wait(lock, [] { return !dataQueue.empty(); });
int value = dataQueue.front();
dataQueue.pop();
}
}
Tracy 会显示:
Lock contention
并告诉你:
Thread A waited 2.1 ms
Thread B waited 5.4 ms
四、视觉 SLAM 示例(Tracking 等待 Frame)
视觉系统常见 pipeline:
Camera Thread
↓
Tracking Thread
↓
Mapping Thread
Tracking 等待 Frame:
cpp
void TrackingThread()
{
while (running)
{
ZoneScoped;
std::unique_lock<std::mutex> lock(frameMutex);
ZoneScopedN("Wait Frame");
frameCV.wait(lock, [] { return !frameQueue.empty(); });
Frame f = frameQueue.front();
frameQueue.pop();
lock.unlock();
ProcessFrame(f);
}
}
Tracy timeline:
Tracking Thread
████ ProcessFrame
██ Wait Frame
████ ProcessFrame
██ Wait Frame
可以直观看到:
等待时间
计算时间
五、统计 Frame Pipeline
SLAM 中推荐这样标记:
cpp
void ProcessFrame()
{
ZoneScopedN("Tracking");
ExtractORB();
PoseEstimation();
LocalBA();
}
Tracy timeline:
Frame 1
Tracking
├─ ExtractORB
├─ PoseEstimation
└─ LocalBA
可以直接看到:
哪个模块最慢
六、Frame profiler(视觉系统强烈推荐)
Tracy 还有 frame profiler。
使用:
cpp
FrameMark;
例如:
cpp
while (running)
{
FrameMark;
ProcessFrame();
}
Tracy会显示:
FPS
Frame time
Frame jitter
非常适合 视觉前端优化。
七、Tracy 的优势
相比传统计时:
chrono
printf
Tracy优势:
| 功能 | Tracy |
|---|---|
| 线程时间线 | ✅ |
| mutex等待 | ✅ |
| CPU cache miss | ✅ |
| 实时可视化 | ✅ |
| 纳秒精度 | ✅ |
八、SLAM项目推荐 instrumentation
建议标记:
Tracking
FeatureExtraction
PoseOptimization
LocalMapping
LoopClosing
示例:
cpp
ZoneScopedN("FeatureExtraction");
九、实际项目性能优化示例
很多视觉系统优化流程:
1 查看线程 timeline
2 找到等待时间
3 找到锁竞争
4 调整 pipeline
例如:
Tracking wait frame 40ms
Mapping compute 200ms
说明:
Mapping 成为瓶颈