0. 简介
Tracy(https://github.com/wolfpld/tracy/releases/latest/download/tracy.pdf)是一款实时、纳秒级分辨率的混合帧和采样剖析器,可用于远程或嵌入式遥测游戏和其他应用程序。它可以对 CPU(C、C++11、Lua)、GPU(OpenGL、Vulkan、Direct3D 11/12、OpenCL)和内存进行剖析。它还能监控线程所持有的锁,并显示竞争发生的位置。Tracy 可以像其他统计分析工具(如 VTune、perf 或 Very Sleepy)一样,对取样的调用堆栈数据进行统计分析,但它主要侧重于对源代码进行手动标记,以便逐帧检查程序的执行情况。你将能清楚地看到哪些函数被调用,在这些函数中花费了多少时间,以及它们在多线程环境中是如何相互影响的。相比之下,统计分析可能会让你看到代码中的hot spots,但却无法准确找出每隔几秒就会出现的半随机帧卡顿的根本原因。尽管 Tracy 以帧剖析为目标,重点分析实时应用程序(如游戏)中的帧时间,但它也适用于不使用帧概念的实用程序。Tracy中分为两个部分,一个是Client ,采样数据的生产者,即我们要分析的程序。另一个是Server ,采样数据的接受者,同时是一个数据的viewer,并支持数据存储,以及导出csv。相关的代码在Github(https://github.com/wolfpld/tracy)上。
具体流程大概为:
1、将Tracy存储库添加到您的项目目录中。
2、项目/tracy/public目录中包含Tracy源文件。
3、将TracyClient.cpp作为源文件添加。
4、将tracy/Tracy.hpp作为包含文件添加。
5、在您有兴趣进行性能分析的每个文件中包含Tracy.hpp。
6、为整个项目定义TRACY_ENABLE。
7、在每个帧循环的末尾添加宏FrameMark。
8、在您的函数定义的第一行添加宏ZoneScoped,以便将其包含在性能分析中。
9、编译并运行您的应用程序和性能分析服务器。
10、在性能分析服务器上点击连接。
11、完成!您正在对您的程序进行性能分析!
1. 所需的源文件
这里是client的关键部分,路径在https://github.com/wolfpld/tracy/tree/master/public下:
两个关键文件夹:common/、client/,以及从根目录复制出来的TracyClient.cpp和相关文件。我也在使用OpenGL进行性能分析,但您可以根据需要删除其他文件。我保留了它们,因为在添加后端时这样做比较容易。我不使用lua,所以我将其移除。我将这些文件复制到我的项目源代码文件夹下的src/tracy/目录中,例如 src/tracy/common。
2. 编译文件
您只需将TracyClient.cpp包含到构建中。根据需要将其添加到您的项目、Makefile或构建脚本中。
您需要两件事:
在您的代码中添加一个定义- TRACY_ENABLE 在您的构建中添加额外的包含路径 - src/tracy/ 然后它就可以找到其包含文件,从而告诉分析器它的存在。如果您删除TRACY_ENABLE,那个构建中就没有分析代码,也没有来自分析器的额外开销。
Premake已经包含了includedirs { "src/tracy/" }和defines { "TRACY_ENABLE" },您可以添加或编辑。在Visual Studio中,对于包含路径,它是 属性 -> C/C++ -> 常规 -> 附加包含目录 对于定义,它是 属性 -> C/C++ -> 预处理器 -> 预处理器定义
对于clang或GCC在命令行上,看起来像这样:-DTRACY_ENABLE -Itracy/
如果是
Windows头文件错误不好处理。如果您遇到一些特别是围绕错误C2011:'sockaddr': 'struct'类型重定义,尝试向您的项目定义中添加一个定义WIN32_LEAN_AND_MEAN。这与windows.h和winsock 2与winsock原始API有关,相当混乱。
您也可以尝试在包含tracy头文件之前定义这个。
2.1 项目打包导入
如果整个项目导入到当中,我们可以发现在CmakeList中有对应的封装
add_library(TracyClient ${TRACY_VISIBILITY} "${TRACY_PUBLIC_DIR}/TracyClient.cpp")
target_compile_features(TracyClient PUBLIC cxx_std_11)
target_include_directories(TracyClient SYSTEM PUBLIC
$<BUILD_INTERFACE:${TRACY_PUBLIC_DIR}>
$<INSTALL_INTERFACE:include>)
target_link_libraries(
TracyClient
PUBLIC
Threads::Threads
${CMAKE_DL_LIBS}
)
然后我们就可以使用下面的代码导入Tracy
if (PERCEPTION_ENABLE_TRACY)
#
target_compile_definitions(${OBJECT_PERCEPTION_LIB_NAME} PUBLIC "PERCEPTION_PROFILE=$<IF:$<BOOL:${PERCEPTION_ENABLE_TRACY}>,1,0>")
target_link_libraries(${OBJECT_PERCEPTION_LIB_NAME} PUBLIC $<IF:$<BOOL:${PERCEPTION_ENABLE_TRACY}>,Tracy::TracyClient,>)
endif()
并指定Tracy相关的配置
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
if (PERCEPTION_ENABLE_TRACY)
message(STATUS "Enable tracy profiling")
set(TRACY_STATIC ON)
option(TRACY_ENABLE "" ON)
set(TRACY_ONLY_IPV4 ON CACHE BOOL "" FORCE )
add_definitions(-DTRACY_CLIENT_ADDRESS="255.255.255.255")
add_subdirectory(tracy)
endif()
2.2 软件打包
使用
cd tracy/profiler/
mkdir build && cd build
cmake ..
make -j10
3. 包含和使用
首先要包含Tracy。如果需要的话,可以使用C头文件。
帧标记
接下来,我们要告诉Tracy你的帧标记在哪里。在引擎的tick或update函数中,添加FrameMark("main");。这样就足够让Tracy开始工作了。如果你构建并编译,你应该能够连接Tracy应用程序并查看帧时序。
打开Tracy性能分析应用程序
既然我们已经在项目中包含了代码,这就是第一步。这意味着我们的游戏(客户端)能够发送信息出去。它需要一个地方来发送信息,要么是一个名为capture的命令行工具,要么是一个带有用户界面的性能分析应用程序。现在我们需要的是带有用户界面的应用程序。
通常你可以从Tracy的发布下载部分获取匹配的版本。7z文件是一个包含文件的zip文件,比如Tracy.exe,这就是应用程序。
运行这个应用程序,然后运行你的游戏,你应该能够看到“已发现的客户端”列表中出现你的应用程序。我在一个名为7dfps-0.0.9.exe的游戏上运行了这个操作,所以点击列表中的7dfps-0.0.9.exe应用程序将启动一个性能分析会话。
请注意,Tracy也可以通过网络进行工作,因此您可以在不同的计算机上运行游戏的Linux版本,并从Windows(或移动设备、或控制台设备等)进行性能分析。
作用域测量
接下来,我们可能想要专门对某些范围进行性能分析,比如render函数。在顶部添加ZoneScopedN("render");,这将为该范围自动添加一个命名区域到性能分析中。还有ZoneScoped;。
就是这样!现在您应该能够在帧内的某个地方看到一个单一的区域。
4. 清洁集成
由于我使用或尝试了多个性能分析工具,包括自定义的工具,我喜欢使用宏来共享性能分析标签。因此,对于Tracy,我有类似这样的东西。
LUXE_LOCK_SCOPE(name) - 定义了一个作用域级的性能分析区域(zone),通常用于监测一个作用域(如一个函数或一个代码块)的执行时间。ZoneScopedN 是 Tracy 的一个宏,它自动记录当前作用域的性能数据,其中 name 提供了该作用域的标签。
LUXE_PROFILE - 类似于 LUXE_LOCK_SCOPE,但通常用于无需自定义名称的情况。ZoneScoped 也是 Tracy 的宏,用于自动记录当前作用域的性能,但不提供自定义名称。
LUXE_PROFILE_FRAME(x) - 用于标记帧的结束,通常用在图形应用或游戏的渲染循环中。FrameMark 是 Tracy 的宏,用于在性能分析中标记一帧的结束。
LUXE_FRAME_MARKER() - 同 LUXE_PROFILE_FRAME(x),但没有参数。
LUXE_LOCK(type, var, name) - 用于跟踪多线程中锁的使用情况。TracyLockableN 是 Tracy 的宏,它记录与指定锁(如互斥锁)相关的性能数据,其中 type 是锁的类型,var 是锁的变量名,name 提供了锁的标签。
LUXE_LOCK_MARKER(var) - 用于标记锁的获取或释放的特定点。LockMark 是 Tracy 的宏,用于在性能分析中标记锁的状态改变。
LUXE_SET_THREAD_NAME(name) - 设置当前线程的名称,使其在 Tracy 的分析工具中显示。这对于区分和跟踪多线程程序中的不同线程非常有用。
LUXE_PROFILE_SECTION(x) - 定义了一个具有自定义名称的性能分析区域,与 LUXE_LOCK_SCOPE 类似。
LUXE_PROFILE_TAG(y, x) - 为当前性能分析区域添加一个文本标签,其中 x 是文本内容。
LUXE_PROFILE_LOG(text, size) - 向 Tracy 日志添加一条消息,text 是消息文本,size 是文本的长度。
LUXE_PROFILE_VALUE(text, value) - 在 Tracy 的实时图表中绘制一个值,text 是该值的标签。
5. 内存分析器
还有一个非常酷的内存分析器,你应该研究一下。luxe中的所有内存都经过自定义分配器,因此很容易添加性能分析。出于某种原因,我使用了C API。12是堆栈深度。
有了这个,我可以看到所有的内存分配、释放、调用堆栈等。
6. OpenGL性能分析
首先通过TracyGpuContext告诉Tracy你的上下文。这是在你的OpenGL上下文初始化之后,任何GPU区域被分析之前调用的。
SDL_GL_CreateContext(window);
TracyGpuContext;
然后定义一个GPU区域宏
然后我可以在作用域内使用它,比如 LUXE_PROFILE_GPU("use program"); 或 LUXE_PROFILE_GPU("draw indexed");
这些被添加在作用域的顶部,任何OpenGL调用都将在其中进行测量,即使它们是异步的。
在交换缓冲区后,添加 TracyGpuCollect;这将把信息发送到Tracy。
SDL_GL_SwapWindow(window);
TracyGpuCollect;
7. 成果展示
7.1 最终结果
凭借如此少的努力,您已经获得了大量信息
7.2 以管理员身份运行
如果你以管理员身份运行,Tracy就可以获取更多信息,比如系统中所有线程的信息,并可以显示代码运行在哪些线程上的上下文切换。它提供了更多的信息
7.3 装配视图
还有拆卸视图,包括指令细节等等。真的非常酷
8. 界面解释
8.1 初始化连接界面
button功能介绍:
📇Manual:点击该按钮,可以跳转到用户使用手册。
🌎Web:点击该按钮,会跳转到Tracy官方主页以及功能演示视频的网页。
💬Chat:点击该按钮,可以跳转到该工具的讨论社区。
🤍Sponsor:点击该按钮,可以给开源社区的建设者们提供资金支持。
🔧:Abort Tracy。
button:可以查看历史连接记录,快速重连之前的IP和对应的端口。
Connect:想要实时捕获,输入IP和port之后点击connect可以查看实时性能。
Open saved trace:如果你想打开保存好的数据文件,你可以点击该按钮,查看捕捉文件的程序性能。
8.2 连接成功信息弹窗
Save trace:使用 Save trace(保存跟踪)按钮将当前配置文件数据保存到文件中。
Stop:点击stop按钮,断开与客户端的连接。
Discard:按Discard按钮用于丢弃当前配置文件数据。
8.3 profiler 主窗口
8.3.1. ⚙️Options:
Draw empty labels :默认情况下,没有任何内容显示的线程会被隐藏。启用此选项后,这些线程还是会显示出来。
Draw frame targets:如果启用,当前所选帧集中任何帧的时间区域、超过指定目标 FPS 值的时间区域将在时间线视图上以红色背景标记。
Draw context switches:勾选该选项,显示在timeline上线程状态的切换。
Darken inactive threads:勾选该选项,将inactive threads在Main Thread Zone 绘制,颜色加深。
Draw CPU data:勾选该选项以绘制CPU数据。
Draw CPU usage graph:勾选该选项会显示CPU使用率图。
Draw stack samples:勾选该选项,将会在Main Thread timeline 上方以点的方式绘制堆栈样本,鼠标移动到点上,会显示具体信息。
Draw CPU zones:勾选该选项,可以显示 CPU 区段。
Zone colors:内核态的调用颜色会比用户态颜色更深。
Zone name shortening:调用接口参数是否显示,有以下选项:
Disabled:不缩短区域名称,名称始终以全名显示。(例如 bool ns::container::add(const float&))。 Minimal length :只有函数名即可。Only normalize :仅去掉函数参数,但不删除名称空间(如 ns::container<>::add() )。AS needed :只有在没有空间显示完整的区名时,才会执行名称缩短步骤。直到名称适合可用空间,或缩写不再可行(例如:container<>:: add() AS needed + normalize :同上,但区段名称归一化总是要执行的、即使整个区域名称符合可用空间。
Draw plots:勾选该选项,可以显示CPU 使用率时间线。
Visible threads:点击该选项,可以指定某些thread是否被展示。
Visable frame sets:点击该选项,可在此处启用或禁用帧集显示。
8.3.2. Messages:切换消息日志窗口,该窗口显示客户端发送的自定义消息。
当你的程序中的代码很庞大、很复杂的时候,你或许会想到打log去调试相应的代码,Messages的功能就在于可以让你快速定位到你的log所在thread。
Tracy 提供了消息日志功能。您可以使用(例如,典型的调试输出)。或者使用TracyMessageL(text) 宏来发送字符串字面信息。如果你想对信息进行颜色编码(例如,使关键信息更容易看清),可以使用 TracyMessageL(text) 宏、可以使用 TracyMessageC(text, size, color) 或 TracyMessageLC(text, color) 宏。
参数:
text:字符串
size:指定显示字符串的大小
color:你可以为你的log进行颜色设置
你也可以在左上角Filter messages中搜索你想要的某一个log 字符串
运行之后的效果:
8.3.3. Find zone:点击按钮可切换查找区段窗口,通过该窗口可检查区段行为统计
Histogram:Self time和Running time不可以同时勾选!!!!
Log values:勾选该选项,可以在y轴上查看调用次数。Log time:勾选该选项,可以在x轴上查看时间分段。Cumulate
time:更改直方图分档值的计算方式。
Self time:删除分析区段中的子区段时间,从而只显示在区段本身(或非仪器功能调用)中花费的时间。或非仪器功能调用中花费的时间。当运行时间激活时无法选择。
Running time:- 删除区的线程执行被操作系统暂停的时间由于其他线程抢占、等待系统资源、锁竞争等原因而被操作系统暂停的时间。仅在
profiler执行上下文切换捕获时可用。当 Self time间激活时无法使用。
Found zones 根据以下标准分组:线程 - 在此模式下,可以查看哪些线程在执行区段。用户文本 - 根据自定义用户文本分割区段。区域名称 - 根据调用设置的名称分组区域。调用堆栈 - 根据起始调用堆栈分组区段。父区 - 根据父区对区段进行分组。这种模式依赖于区段层次结构,而不是调用堆栈信息。无分组 - 禁用区段分组
8.3.4. Statistics:查看时间轴视图可以让你对事物有一个更具体的看法。不过,有时你想查看程序行为的总体概览。例如,您想知道哪个函数占用了程序最多的执行时间。统计窗口恰好能为您提供这些信息。
statistics主要有两种模式:Instrumentation mode && Sampling
勾选Instrmentation,可以看到以下基本信息:Name、Location、Total time、Counts、MTPC
Sampling与Instrmentation有相同之处,但也有几点不同 @ Address:Sampling可以勾选Address选项查看程序的二进制地址 Show all:Samping可以勾选Show all选项查看该程序的所有调用
8.3.5. Memory:(打开抓取的tracy文件,目前没有memory信息,待补充
8.3.6. Compare:该按钮的功能是将程序之间的性能进行比较,在开始工作时,您需要记录一条代表程序通常行为的参考轨迹。然后,在代码优化完成后,再保存记录优化后的程序。最后,打开优化后的程序,在比较窗口中选择 i Open second选项,并加载原来的程序。
通常情况下,轨迹是用颜色和符号编码的。当前轨迹用黄色符号标记,外部轨迹用红色 v 符号标记。
9. 参考链接
https://blog.csdn.net/ahuyccc/article/details/134125422
https://luxeengine.com/integrating-tracy-profiler-in-cpp/
https://blog.csdn.net/ahuyccc/article/details/134125422
招募要求
完成符合要求的机器人相关视频制作
总时长需达到 3小时以上
视频内容需为精品课程,确保高质量和专业性
讲师奖励
享受课程收入分成
赠送 2门 古月学院在售精品课程(训练营除外)
联系我们
添加工作人员微信:GYH-xiaogu
点击“阅读原文”查看详情