[{"data":1,"prerenderedAt":495},["ShallowReactive",2],{"page-\u002Fcpp\u002F性能分析工具tracy":3},{"id":4,"title":5,"body":6,"description":50,"extension":488,"meta":489,"navigation":490,"path":491,"seo":492,"stem":493,"__hash__":494},"content\u002Fcpp\u002F性能分析工具Tracy.md","性能分析工具Tracy",{"type":7,"value":8,"toc":476},"minimark",[9,13,17,20,31,41,44,59,62,66,73,76,79,82,85,88,91,94,101,110,115,127,132,137,140,143,146,149,152,155,265,331,334,407,412,415,472],[10,11,12],"h2",{"id":12},"配置",[14,15,16],"p",{},"Tracy工具是支持分析 CPU（为 C、C++ 和 Lua 集成提供直接支持。同时，互联网上存在许多其他语言的第三方绑定，例如 Rust 、Zig、C # 、 OCaml 、 Odin等。 ）、GPU（所有主要图形 API：OpenGL、Vulkan、Direct3D 11\u002F12、OpenCL。）、内存分配、锁定、上下文切换、自动将屏幕截图归因于捕获的帧等等。",[14,18,19],{},"有两个部分组成，一个是客户端，一个是服务器。客户端负责的是采样数据，也就是我们要分析的程序，服务器是采样数据的接受者，同时也是一个数据的viewer，可以支持数据存储和导出csv。",[14,21,22,23,30],{},"它的使用方法简单，也可以十分方便地集成在我们的项目中，一个是使用vcpkg来管理这些模块，一个是使用camke 3.11版本的fetch来作为CMake 的 ",[24,25,26],"strong",{},[27,28,29],"code",{},"FetchContent"," 模块。",[32,33,34],"blockquote",{},[14,35,36,40],{},[37,38,39],"span",{},"!tip"," 他会自动下载到我们的out文件夹也就是构建目录下的_deps目录里面，会自动调用add_subdirectory()，将tracy的源码直接纳入我们的工程中，tracy会和我们的模块一起编译。\n这种做法有很好的优点，一个是全自动化，一个是Debug友好，我们可以直接单步跳入，和保持静态链接一致性。",[14,42,43],{},"我们就可以直接使用，它会在编译之后一起放在输出模块中，我们只需要在可执行文件中将它链接进去就行：",[45,46,51],"pre",{"className":47,"code":48,"language":49,"meta":50,"style":50},"language-cmake shiki shiki-themes github-light github-dark","target_link_libraries(DrawTriangle PRIVATE Graphics Foundation TracyClient)\n","cmake","",[27,52,53],{"__ignoreMap":50},[37,54,57],{"class":55,"line":56},"line",1,[37,58,48],{},[10,60,61],{"id":61},"追踪",[63,64,65],"h3",{"id":65},"整个函数的追踪的执行时间",[14,67,68,69,72],{},"我们可以在main函数下方直接插入ZoneScoped，这是Tracy中最常用的最标准的做法，如果没有给他命名，那么他就会使用cpp的预处理器比如说（",[24,70,71],{},"FUNCTION__或者是__PRETTT_FUNCITON","），这会自动抓取当前函数的命名。",[14,74,75],{},"他会追踪从这行开始到大括号结束的整个范围，这个在CPP中被称为RAII机制。它的开销极低，只有几纳秒到几十纳秒的延迟，并且我们编译Release版本的时候不加TRACY_ENABLE宏就不会启用，会被预处理器直接替换为空白，不会产生任何机器码，可以放心使用。\n![[Pasted image 20260101205838.png]]",[63,77,78],{"id":78},"标记帧边界",[14,80,81],{},"还有一个宏叫做FrameMark，他记录的是横向的信息比如说FPS和帧耗时，如果没有他的话，我们只能看到散乱的函数执行记录，有了它，Tracy的顶部界面会有FPS实时曲线，有帧耗时，会有帧过滤。",[14,83,84],{},"这个通常放在主循环的最后。![[Pasted image 20260101205957.png]]",[14,86,87],{},"![[Pasted image 20260101210021.png]]",[63,89,90],{"id":90},"内存追踪工具",[14,92,93],{},"如果我们需要开启内存追踪，我们需要在cmake中进行配置：![[Pasted image 20260101211643.png]]\n开启这个编译选项，然后在我们的应用文件中编写相关逻辑![[Pasted image 20260101211728.png]]\n重载操作符，来追踪所有的内存分配，所有的new\u002Fdelate都会在Tracy中显示堆栈信息。",[95,96,97],"ol",{},[98,99,100],"li",{},"Windows\u002FMSVC 支持：",[102,103,104,107],"ul",{},[98,105,106],{},"使用 _aligned_malloc 和 _aligned_free（Windows 特定 API）",[98,108,109],{},"包含 \u003Cmalloc.h> 头文件",[95,111,112],{},[98,113,114],{},"Linux\u002F其他平台支持：",[102,116,117,120],{},[98,118,119],{},"使用 std::aligned_alloc 和 std::free",[98,121,122,123],{},"包含 ",[124,125,126],"cstdlib",{}," 头文件",[95,128,129],{},[98,130,131],{},"平台检测：",[102,133,134],{},[98,135,136],{},"使用 #ifdef _WIN32 来区分 Windows 和其他平台",[63,138,139],{"id":139},"profiler工具",[14,141,142],{},"我们打开tracy官方的工具，有一个叫做tracy-profiler的工具，打开后我们保证之前的程序在运行，就可以链接上去，看到我们想看的任何信息：",[14,144,145],{},"![[Pasted image 20260101210138.png]]\n![[Pasted image 20260101210142.png]]",[14,147,148],{},"这个工具还提供了很多的其他小功能，比如说统计功能，还有内存占用分析工具等。",[63,150,151],{"id":151},"常用的快捷键",[14,153,154],{},"这是在长达几分钟的录制中左右穿梭的核心：",[156,157,158,175],"table",{},[159,160,161],"thead",{},[162,163,164,170],"tr",{},[165,166,167],"th",{},[24,168,169],{},"快捷键",[165,171,172],{},[24,173,174],{},"动作",[176,177,178,193,206,216,226,240,254],"tbody",{},[162,179,180,186],{},[181,182,183],"td",{},[24,184,185],{},"鼠标滚轮",[181,187,188,189,192],{},"以光标位置为中心 ",[24,190,191],{},"缩放"," 时间轴（放大看微秒，缩小看全局）。",[162,194,195,200],{},[181,196,197],{},[24,198,199],{},"左键按住并拖动",[181,201,202,205],{},[24,203,204],{},"平移"," 时间轴。",[162,207,208,213],{},[181,209,210],{},[24,211,212],{},"W \u002F S",[181,214,215],{},"放大 \u002F 缩小（滚轮的键盘替代方案）。",[162,217,218,223],{},[181,219,220],{},[24,221,222],{},"A \u002F D",[181,224,225],{},"向左 \u002F 向右 平移时间轴。",[162,227,228,233],{},[181,229,230],{},[24,231,232],{},"Home",[181,234,235,236,239],{},"跳转到录制的最 ",[24,237,238],{},"开始","。",[162,241,242,247],{},[181,243,244],{},[24,245,246],{},"End",[181,248,249,250,253],{},"跳转到录制的 ",[24,251,252],{},"末尾","（实时查看当前状态）。",[162,255,256,263],{},[181,257,258,259,262],{},"当你想在成千上万个 ",[27,260,261],{},"ZoneScoped"," 中找到你的 Yoga 布局函数时：",[181,264],{},[156,266,267,279],{},[159,268,269],{},[162,270,271,275],{},[165,272,273],{},[24,274,169],{},[165,276,277],{},[24,278,174],{},[176,280,281,295,308,321],{},[162,282,283,288],{},[181,284,285],{},[24,286,287],{},"Ctrl + F",[181,289,290,291,294],{},"打开 ",[24,292,293],{},"全局搜索","。可以搜索函数名、源文件名或自定义消息。",[162,296,297,302],{},[181,298,299],{},[24,300,301],{},"N",[181,303,290,304,307],{},[24,305,306],{},"Find Zone"," 窗口，快速定位特定名称的区域。",[162,309,310,315],{},[181,311,312],{},[24,313,314],{},"Space (空格)",[181,316,317,320],{},[24,318,319],{},"居中并高亮"," 当前选中的区域。",[162,322,323,328],{},[181,324,325],{},[24,326,327],{},"Enter",[181,329,330],{},"进入选中区域的详细统计信息视图。",[14,332,333],{},"测量和分析工具",[156,335,336,348],{},[159,337,338],{},[162,339,340,344],{},[165,341,342],{},[24,343,169],{},[165,345,346],{},[24,347,174],{},[176,349,350,363,376,390],{},[162,351,352,357],{},[181,353,354],{},[24,355,356],{},"鼠标中键 (单击并拖动)",[181,358,359,362],{},[24,360,361],{},"测量工具","。非常有用的“神技”，可以测量时间轴上任意两点之间的时间差（例如：测量从输入事件到画面显示的真实延迟）。",[162,364,365,370],{},[181,366,367],{},[24,368,369],{},"S",[181,371,290,372,375],{},[24,373,374],{},"Statistics (统计)"," 视图。查看所有函数的平均耗时、总耗时百分比等。",[162,377,378,383],{},[181,379,380],{},[24,381,382],{},"C",[181,384,385,386,389],{},"开启\u002F关闭 ",[24,387,388],{},"连接线","。显示父子函数之间的调用关系。",[162,391,392,397],{},[181,393,394],{},[24,395,396],{},"M",[181,398,290,399,402,403,406],{},[24,400,401],{},"Messages"," 窗口，查看代码中 ",[27,404,405],{},"TracyMessage"," 发出的调试日志。",[14,408,409],{},[24,410,411],{},"采样与内存 (Sampling & Memory)",[14,413,414],{},"针对 AOT 分析和内存监控需求：",[156,416,417,429],{},[159,418,419],{},[162,420,421,425],{},[165,422,423],{},[24,424,169],{},[165,426,427],{},[24,428,174],{},[176,430,431,445,458],{},[162,432,433,438],{},[181,434,435],{},[24,436,437],{},"Y",[181,439,440,441,444],{},"切换 ",[24,442,443],{},"采样堆栈 (Callstack)"," 的显示。",[162,446,447,452],{},[181,448,449],{},[24,450,451],{},"L",[181,453,440,454,457],{},[24,455,456],{},"锁竞争 (Locks)"," 视图（如果你的 UI 框架涉及多线程锁）。",[162,459,460,465],{},[181,461,462],{},[24,463,464],{},"I",[181,466,467,468,471],{},"查看当前的 ",[24,469,470],{},"系统信息","（CPU 型号、频率、执行上下文切换等）。",[473,474,475],"style",{},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":50,"searchDepth":477,"depth":477,"links":478},2,[479,480],{"id":12,"depth":477,"text":12},{"id":61,"depth":477,"text":61,"children":481},[482,484,485,486,487],{"id":65,"depth":483,"text":65},3,{"id":78,"depth":483,"text":78},{"id":90,"depth":483,"text":90},{"id":139,"depth":483,"text":139},{"id":151,"depth":483,"text":151},"md",{},true,"\u002Fcpp\u002F性能分析工具tracy",{"description":50},"cpp\u002F性能分析工具Tracy","c7uaRYSENa0kAhwl4ehDfc99P3apmjV6w9VT3-R0QZ8",1791042464543]