Compare commits

..

36 Commits

Author SHA1 Message Date
Bartosz Taudul
c556831ddc Release 0.12.2. 2025-06-25 23:55:40 +02:00
Bartosz Taudul
8a8e16a559 Merge pull request #1083 from siliceum/bugfix/clear-button-find-zone
Fix Clear button behavior in Find Zone
2025-06-23 14:30:49 +02:00
Bartosz Taudul
be89f228ee Merge pull request #1081 from boguscoder/boguscoder-lua
Make TracyLua buildable with TRACY_NO_CALLSTACK
2025-06-21 00:12:12 +02:00
Oleg Bogdanov
4f9107fac5 Make TracyLua buildable with TRACY_NO_CALLSTACK
See discussion https://github.com/wolfpld/tracy/issues/1080
2025-06-20 12:45:54 -07:00
Antoine Mura
17ab46c539 Fix Clear Button in Find Zone 2025-06-20 11:05:02 +02:00
Bartosz Taudul
8caf4f0d60 Merge pull request #1078 from mcourteaux/master
Fix MinGW build.
2025-06-19 21:07:12 +02:00
Martijn Courteaux
8b1576170d Disable Windows __try1 __except1 mechanic to be cross compilable from Linux. 2025-06-19 17:11:28 +02:00
mncat77
1d6fda26ea Fix MinGW build 2025-06-19 17:11:28 +02:00
Bartosz Taudul
581e9cb28e Merge pull request #1076 from boguscoder/regex_fix
relax regex match in symbolication substitution
2025-06-19 11:34:06 +02:00
Oleg Bogdanov
84cbf46cc5 relax regex match in symbolication substitution
See discussion https://github.com/wolfpld/tracy/issues/1075
2025-06-18 18:50:05 -07:00
Bartosz Taudul
250daeabe7 Merge pull request #1074 from boguscoder/master
Fixing typo in log statement of symbolication
2025-06-18 23:16:48 +02:00
Oleg Bogdanov
1fa69045a3 Fixing typo in log statement of symbolication 2025-06-18 14:10:15 -07:00
Bartosz Taudul
1a872faae6 Update can't be built without NO_STATISTICS. 2025-06-18 20:00:34 +02:00
Bartosz Taudul
f1119d88b9 Merge pull request #1072 from neobrain/profiler_include_dirs
Add include directories for pkg-config dependencies in the profiler build
2025-06-17 18:40:40 +02:00
Tony Wasserka
22e580d4c0 Add include directories for pkg-config dependencies in the profiler build 2025-06-17 17:39:57 +02:00
Bartosz Taudul
764624d3d1 Merge pull request #1070 from rmarker/flameLimit
Add limit range for flame graph.
2025-06-15 17:03:04 +02:00
rmarker
e1b325741e Add limit range for flame graph.
Allow restricting the flame graph to a specific time range.
Similar to the existing range limits for other tools, such as for
statistics.
2025-06-15 17:41:27 +09:30
Bartosz Taudul
b69813f077 Fix CMake stupidity with Ninja vs Unix Makefiles generators. 2025-06-14 12:07:43 +02:00
Bartosz Taudul
d181e80c29 Fix builds out of git repository. 2025-06-14 11:56:17 +02:00
Bartosz Taudul
650c98ece7 Relase 0.12.1. 2025-06-07 16:59:25 +02:00
Bartosz Taudul
310c9389b2 Update license list. 2025-06-07 16:45:25 +02:00
Bartosz Taudul
e660821d75 Remove Windows hacks for including license in the manual. 2025-06-07 16:32:06 +02:00
Bartosz Taudul
fae74430c5 Document flame graph. 2025-06-07 16:31:13 +02:00
Bartosz Taudul
3100c39a68 Remove ObjC header from Meson build.
Meson decides to be special again:

"ERROR: No specified compiler can handle file public/tracy/TracyMetal.hmm"
2025-06-07 13:45:17 +02:00
Bartosz Taudul
0dd5c8b507 Add TracyCUDA.hpp and TracyMetal.hmm to meson include list. 2025-06-07 13:35:57 +02:00
Bartosz Taudul
a0b2a1d4bc Add TracyCUDA.hpp to CMake include list. 2025-06-07 13:35:44 +02:00
Bartosz Taudul
09558a0347 Set proper tracy include dir in CMake config. 2025-06-07 13:33:00 +02:00
Bartosz Taudul
b57f08f166 Merge pull request #1064 from eigenraven/raven/install-metal-header
Add TracyMetal.hmm to the installed headers list in CMake
2025-06-06 14:33:32 +02:00
Raven Szewczyk
7f56f1d182 Add TracyMetal.hmm to the installed headers list in CMake 2025-06-06 13:17:32 +01:00
Bartosz Taudul
7e833e7ddc Merge pull request #1061 from c-cube/simon/check-in-import-fuchsia
add a sanity check to fuchsia importer
2025-06-02 17:45:58 +02:00
Simon Cruanes
bbf225b788 add a sanity check to fuchsia importer 2025-06-02 10:41:25 -04:00
Bartosz Taudul
18242189e1 Merge pull request #1060 from evan-barentin/eb-fix-git-ref-call-outside-source
Fix profiler compilation when build directory is outside the source directory
2025-06-02 16:03:24 +02:00
Evan Barentin
9becb3221d Fix: precise source directory to git log call 2025-06-02 13:37:51 +02:00
Bartosz Taudul
2875926cdb Disable debug functionality in ppqsort.
Apple's stdlib doesn't implement syncstream.
2025-06-01 19:51:36 +02:00
Bartosz Taudul
79c5bdcf62 Merge pull request #1055 from produktivkraft/osx_vscroll
fix vertical scroll bar lost  on macos
2025-05-31 18:39:17 +02:00
Allen Guo
b8267a1660 fix vertical scroll bar lost on macos 2025-05-31 23:40:56 +08:00
24 changed files with 296 additions and 32 deletions

View File

@@ -13,9 +13,6 @@ jobs:
steps:
- uses: actions/checkout@v4
- name: Fix stupidity
run: |
cp LICENSE LICENSE.
- name: Compile LaTeX
uses: xu-cheng/latex-action@v3
with:

View File

@@ -49,7 +49,7 @@ target_compile_features(TracyClient PUBLIC cxx_std_11)
set_target_properties(TracyClient PROPERTIES INTERPROCEDURAL_OPTIMIZATION ${LTO_SUPPORTED})
target_include_directories(TracyClient SYSTEM PUBLIC
$<BUILD_INTERFACE:${TRACY_PUBLIC_DIR}>
$<INSTALL_INTERFACE:include>)
$<INSTALL_INTERFACE:include/tracy>)
target_link_libraries(
TracyClient
PUBLIC
@@ -61,7 +61,7 @@ if(TRACY_Fortran)
add_library(TracyClientF90 ${TRACY_VISIBILITY} "${TRACY_PUBLIC_DIR}/TracyClient.F90")
target_include_directories(TracyClientF90 PUBLIC
$<BUILD_INTERFACE:${PROJECT_BINARY_DIR}>
$<INSTALL_INTERFACE:include>)
$<INSTALL_INTERFACE:include/tracy>)
target_link_libraries(
TracyClientF90
PUBLIC
@@ -164,9 +164,11 @@ endif()
set(tracy_includes
${TRACY_PUBLIC_DIR}/tracy/TracyC.h
${TRACY_PUBLIC_DIR}/tracy/Tracy.hpp
${TRACY_PUBLIC_DIR}/tracy/TracyCUDA.hpp
${TRACY_PUBLIC_DIR}/tracy/TracyD3D11.hpp
${TRACY_PUBLIC_DIR}/tracy/TracyD3D12.hpp
${TRACY_PUBLIC_DIR}/tracy/TracyLua.hpp
${TRACY_PUBLIC_DIR}/tracy/TracyMetal.hmm
${TRACY_PUBLIC_DIR}/tracy/TracyOpenCL.hpp
${TRACY_PUBLIC_DIR}/tracy/TracyOpenGL.hpp
${TRACY_PUBLIC_DIR}/tracy/TracyVulkan.hpp)

25
NEWS
View File

@@ -2,6 +2,31 @@ Note: There is no guarantee that version mismatched client and server will
be able to talk with each other. Network protocol breakages won't be listed
here.
v0.12.2 (2025-06-25)
--------------------
- Fixed builds made out of git checkout directory.
- Added range limits for flame graph.
- Fixed wayland include paths for distros that use non-standard package
layouts.
- Workarounded MinGW build problems. Safe symbol retrieval is not available
on this platform.
- Fixed Lua bindings when TRACY_NO_CALLSTACK is defined.
v0.12.1 (2025-06-07)
--------------------
- Fixed window size calculation on macOS, most notably enabling the vertical
timeline scroll bar.
- Made debug builds of the GUI profiler work with broken Apple compiler.
- Fixed profiler compilation when build directory is outside the source
directory.
- Set proper include path when using CMake integration.
- Added the Tracy Metal and CUDA headers to CMake install configuration.
- Documented flame graphs.
v0.12.0 (2025-05-30)
--------------------

View File

@@ -0,0 +1,14 @@
diff --git i/include/ppqsort/parameters.h w/include/ppqsort/parameters.h
index 115c3a1..3f4b669 100644
--- i/include/ppqsort/parameters.h
+++ w/include/ppqsort/parameters.h
@@ -3,7 +3,8 @@
#include <bit>
#include <execution>
-#ifndef NDEBUG
+//#ifndef NDEBUG
+#if 0
#include <bitset>
#include <iostream>
#include <syncstream>

View File

@@ -187,5 +187,7 @@ CPMAddPackage(
NAME PPQSort
GITHUB_REPOSITORY GabTux/PPQSort
VERSION 1.0.5
PATCHES
"${CMAKE_CURRENT_LIST_DIR}/ppqsort-nodebug.patch"
EXCLUDE_FROM_ALL TRUE
)

View File

@@ -188,6 +188,12 @@ std::pair<bool, Record> read_next_record(std::vector<uint8_t> const &input, size
CHECK_BOUND(offset + 8*len_word);
Record r{(uint64_t *)&input[offset], len_word, header};
if (len_word == 0) {
fprintf(stderr, "warning: invalid record with length=0 at offset %" PRIu64 "\n", offset); \
return std::make_pair(false,Record{}); \
}
offset += 8 * len_word;
return std::make_pair(true, r);
}

View File

@@ -3223,7 +3223,7 @@ The control menu (top row of buttons) provides access to various profiler featur
\item \emph{\faTags{} Messages} -- Toggles the message log window (section~\ref{messages}), which displays custom messages sent by the client, as described in section~\ref{messagelog}.
\item \emph{\faSearch{} Find} -- This buttons toggles the find zone window, which allows inspection of zone behavior statistics (section~\ref{findzone}).
\item \emph{\faSortAmountUp{} Statistics} -- Toggles the statistics window, which displays zones sorted by their total time cost (section~\ref{statistics}).
\item \emph{\faFire{} Flame} -- Enables the flame graph window.
\item \emph{\faFire{} Flame} -- Enables the flame graph window (section~\ref{flamegraph}).
\item \emph{\faMemory{} Memory} -- Various memory profiling options may be accessed here (section~\ref{memorywindow}).
\item \emph{\faBalanceScale{} Compare} -- Toggles the trace compare window, which allows you to see the performance difference between two profiling runs (section~\ref{compare}).
\item \emph{\faFingerprint{} Info} -- Show general information about the trace (section~\ref{traceinfo}).
@@ -3658,6 +3658,7 @@ To define a time range, drag the \LMB{}~left mouse button over the timeline view
\begin{itemize}
\item \emph{\faSearch{}~Limit find zone time range} -- this will limit find zone results. See chapter~\ref{findzone} for more details.
\item \emph{\faSortAmountUp{}~Limit statistics time range} -- selecting this option will limit statistics results. See chapter~\ref{statistics} for more details.
\item \emph{\faFire{}~Limit flame graph time range} -- limits flame graph results. Refer to chapter~\ref{flamegraph}.
\item \emph{\faHourglassHalf{}~Limit wait stacks time range} -- limits wait stacks results. Refer to chapter~\ref{waitstackswindow}.
\item \emph{\faMemory{}~Limit memory time range} -- limits memory results. Read more about this in chapter~\ref{memorywindow}.
\item \emph{\faStickyNote{}~Add annotation} -- use to annotate regions of interest, as described in chapter~\ref{annotatingtrace}.
@@ -4050,6 +4051,67 @@ To see what changes were made in the source code between the two compared traces
Please note that changes will be registered only if the file has the same name and location in both traces. Tracy does not resolve file renames or moves.
\subsection{Flame graph}
\label{flamegraph}
The flame graph is a way of showing the general performance characteristics of a program on a single chart. While the timeline view displays each zone individually, the flame graph aggregates all zones into a tree structure that better conveys where the application spends its time in relation to the program flow.
Figure~\ref{flamegraphfigure} shows an example flame graph. The graph shows that the program has been running for 11 seconds. Looking at the top row of the zones tree, we see that during this time one second was spent in the \emph{Init} zone and the remaining ten seconds in the \emph{Game loop} zone.
The rows below show the zone times of the child functions. For example, the \emph{Game loop} zone goes into the \emph{Logic update} and \emph{Render} zones. Only one aggregated \emph{Logic update} and \emph{Render} zone is displayed, even though the \emph{Game loop} would enter these functions hundreds of times in a 10-second span.
There are two different \emph{Raycast} zones on the graph. This is because there are two code paths that lead to this function, and the graph distinguishes between them.
\begin{figure}[h]
\centering\begin{tikzpicture}
\foreach \x in {0,1,2,...,10} {
\draw (\x+0, 0) -- +(0, -0.4);
\draw (\x+0.1, 0) -- +(0, -0.2);
\draw (\x+0.2, 0) -- +(0, -0.2);
\draw (\x+0.3, 0) -- +(0, -0.2);
\draw (\x+0.4, 0) -- +(0, -0.2);
\draw (\x+0.5, 0) -- +(0, -0.3);
\draw (\x+0.6, 0) -- +(0, -0.2);
\draw (\x+0.7, 0) -- +(0, -0.2);
\draw (\x+0.8, 0) -- +(0, -0.2);
\draw (\x+0.9, 0) -- +(0, -0.2); }
\draw (11, 0) -- +(0, -0.4);
\draw (-0.2, -0.4) node[anchor=north west] {0};
\draw (1.85, -0.4) node[anchor=north west] {2 \si{\second}};
\draw (3.85, -0.4) node[anchor=north west] {4 \si{\second}};
\draw (5.85, -0.4) node[anchor=north west] {6 \si{\second}};
\draw (7.85, -0.4) node[anchor=north west] {8 \si{\second}};
\draw (9.85, -0.4) node[anchor=north west] {10 \si{\second}};
\draw(0, -1) rectangle+(1, -0.5) node[midway] {Init};
\draw(1, -1) rectangle+(10, -0.5) node[midway] {Game loop};
\draw(0, -1.5) rectangle+(0.1, -0.5);
\draw(0.1, -1.5) rectangle+(0.3, -0.5);
\draw(0.4, -1.5) rectangle+(0.2, -0.5);
\draw(1, -1.5) rectangle+(7, -0.5) node[midway] {Logic update};
\draw(8, -1.5) rectangle+(2, -0.5) node[midway] {Render};
\draw(1, -2) rectangle+(3, -0.5) node[midway] {AI};
\draw(4, -2) rectangle+(2, -0.5) node[midway] {Projectiles};
\draw(6, -2) rectangle+(1.5, -0.5) node[midway] {Particles};
\draw(1, -2.5) rectangle+(1, -0.5) node[midway] {A*};
\draw(2, -2.5) rectangle+(1.5, -0.5) node[midway] {Raycast};
\draw(4, -2.5) rectangle+(1.25, -0.5) node[midway] {Raycast};
\end{tikzpicture}
\caption{Flame graph.}
\label{flamegraphfigure}
\end{figure}
The default sorting order of the zones on a flame graph \emph{approximates} the real call ordering. The program will call \emph{Init} before entering \emph{Game loop}, and each frame update will call \emph{Logic update} before doing \emph{Render}. This order is preserved. However, the logic update function may need to interleave the processing of AI entities and projectile movement\footnote{Such design would be less than ideal, but sometimes that's how you have to go.}. This interleaving won't be represented on the graph. Each zone will be placed in the appropriate bin in a first-come, first-served manner.
You can use an alternative sorting method by enabling the \emph{Sort by time} option. This will place the most time-consuming zones first (to the left) on the graph.
Similar to the statistics window (section~\ref{statistics}), the flame graph can operate in two modes: \emph{\faSyringe{}~Instrumentation} and \emph{\faEyeDropper{}~Sampling}. In the instrumentation mode, the graph represents the zones you put in your program. In the sampling mode, the graph is constructed from the automatically captured call stack data (section~\ref{sampling}).
In the sampling mode you can exclude \emph{external frames} from the graph, which typically would be internal implementation details of starting threads, handling smart pointers, and other such things that are quick to execute and not really interesting. This leaves only the frames from your code. One exception is \emph{external tails}, or calls that your code makes that do not eventually land in your application down the call chain. Think of functions that write to a file or send data on the network. These can be time-consuming, and you may want to see them. There is a separate option to disable these.
The flame graph can be restricted to a specific time extent using the \emph{Limit range} option (chapter~\ref{timeranges}). You can access more options through the \emph{\faRuler{}~Limits} button, which will open the time range limits window, described in section~\ref{timerangelimits}.
\subsection{Memory window}
\label{memorywindow}
@@ -4461,7 +4523,7 @@ A new view-sized annotation can be added in this window by pressing the \emph{\f
\subsection{Time range limits}
\label{timerangelimits}
This window displays information about time range limits (section~\ref{timeranges}) for find zone (section~\ref{findzone}), statistics (section~\ref{statistics}), memory (section~\ref{memorywindow}) and wait stacks (section~\ref{waitstackswindow}) results. Each limit can be enabled or disabled and adjusted through the following options:
This window displays information about time range limits (section~\ref{timeranges}) for find zone (section~\ref{findzone}), statistics (section~\ref{statistics}), flame graph (section~\ref{flamegraph}), memory (section~\ref{memorywindow}) and wait stacks (section~\ref{waitstackswindow}) results. Each limit can be enabled or disabled and adjusted through the following options:
\begin{itemize}
\item \emph{Limit to view} -- Set the time range limit to current view.
@@ -4587,7 +4649,7 @@ The profiler never prunes user settings.
\section{License}
\verbatiminput{../LICENSE.}
\verbatiminput{../LICENSE}
\section{Inventory of external libraries}
@@ -4600,6 +4662,7 @@ The following libraries are included with and used by the Tracy Profiler. Entrie
\item libbacktrace \faStar{} -- \url{https://github.com/ianlancetaylor/libbacktrace}
\item Zstandard -- \url{https://github.com/facebook/zstd}
\item Diff Template Library -- \url{https://github.com/cubicdaiya/dtl}
\item Capstone -- \url{https://github.com/capstone-engine/capstone}
\end{itemize}
\item 2-clause BSD license
@@ -4622,6 +4685,7 @@ The following libraries are included with and used by the Tracy Profiler. Entrie
\item Native File Dialog Extended -- \url{https://github.com/btzy/nativefiledialog-extended}
\item IconFontCppHeaders -- \url{https://github.com/juliettef/IconFontCppHeaders}
\item pdqsort -- \url{https://github.com/orlp/pdqsort}
\item glfw -- \url{https://www.glfw.org/}
\end{itemize}
\item MIT license
@@ -4631,6 +4695,14 @@ The following libraries are included with and used by the Tracy Profiler. Entrie
\item robin-hood-hashing -- \url{https://github.com/martinus/robin-hood-hashing}
\item SPSCQueue \faStar{} -- \url{https://github.com/rigtorp/SPSCQueue}
\item ini -- \url{https://github.com/rxi/ini}
\item PPQSort -- \url{https://github.com/GabTux/PPQSort}
\item wayland-protocols -- \url{https://gitlab.freedesktop.org/wayland/wayland-protocols}
\item JSON for Modern C++ -- \url{https://github.com/nlohmann/json}
\end{itemize}
\item FreeType License
\begin{itemize}
\item FreeType -- \url{https://freetype.org/}
\end{itemize}
\item Apache license 2.0

View File

@@ -1,4 +1,4 @@
project('tracy', ['cpp'], version: '0.12.0', meson_version: '>=1.3.0', default_options : ['cpp_std=c++11'])
project('tracy', ['cpp'], version: '0.12.2', meson_version: '>=1.3.0', default_options : ['cpp_std=c++11'])
# internal compiler flags
tracy_compile_args = []
@@ -132,6 +132,7 @@ endif
includes = [
'public/tracy/TracyC.h',
'public/tracy/Tracy.hpp',
'public/tracy/TracyCUDA.hpp',
'public/tracy/TracyD3D11.hpp',
'public/tracy/TracyD3D12.hpp',
'public/tracy/TracyLua.hpp',

View File

@@ -106,6 +106,7 @@ set(LIBS "")
if(USE_WAYLAND)
pkg_check_modules(WAYLAND REQUIRED egl wayland-egl wayland-cursor xkbcommon)
set(INCLUDES "${INCLUDES};${WAYLAND_INCLUDE_DIRS}")
set(LIBS "${LIBS};${WAYLAND_LIBRARIES}")
set(PROFILER_FILES ${PROFILER_FILES}
src/BackendWayland.cpp
@@ -193,7 +194,8 @@ endif()
find_package(Git)
if(Git_FOUND)
add_custom_target(git-ref
COMMAND ${GIT_EXECUTABLE} log -1 "--format=#pragma once %nnamespace tracy { static inline const char* GitRef = %x22%h%x22; }" ${GIT_REV} > GitRef.hpp.tmp
COMMAND ${CMAKE_COMMAND} -E echo "#pragma once" > GitRef.hpp.tmp
COMMAND ${GIT_EXECUTABLE} -C ${CMAKE_CURRENT_SOURCE_DIR} log -1 "--format=namespace tracy { static inline const char* GitRef = %x22%h%x22; }" ${GIT_REV} >> GitRef.hpp.tmp || echo "namespace tracy { static inline const char* GitRef = \"unknown\"; }" >> GitRef.hpp.tmp
COMMAND ${CMAKE_COMMAND} -E copy_if_different GitRef.hpp.tmp GitRef.hpp
BYPRODUCTS GitRef.hpp GitRef.hpp.tmp
VERBATIM

View File

@@ -166,6 +166,10 @@ void Backend::NewFrame( int& w, int& h )
}
glfwGetFramebufferSize( s_window, &w, &h );
#if defined( __APPLE__ )
w = static_cast<int>( w / scale );
h = static_cast<int>( h / scale );
#endif
m_w = w;
m_h = h;

View File

@@ -5,7 +5,7 @@ namespace tracy
{
constexpr ProtocolHistory_t ProtocolHistoryArr[] = {
{ 74, FileVersion( 0, 12, 0 ) },
{ 74, FileVersion( 0, 12, 0 ), FileVersion( 0, 12, 2 ) },
{ 69, FileVersion( 0, 11, 1 ) },
{ 66, FileVersion( 0, 11, 0 ) },
{ 64, FileVersion( 0, 10, 0 ) },

View File

@@ -808,6 +808,7 @@ bool View::DrawImpl()
sprintf( tmp, "%s###Profiler", m_worker.GetCaptureName().c_str() );
ImGui::SetNextWindowSize( ImVec2( 1550, 800 ), ImGuiCond_FirstUseEver );
ImGui::Begin( tmp, keepOpenPtr, ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoBringToFrontOnFocus );
ImGuiViewport* viewport = ImGui::GetMainViewport();
#endif
if( !m_staticView )
@@ -1172,6 +1173,12 @@ bool View::DrawImpl()
m_statRange.min = s;
m_statRange.max = e;
}
if( ImGui::Selectable( ICON_FA_FIRE_FLAME_CURVED " Limit flame time range" ) )
{
m_flameRange.active = true;
m_flameRange.min = s;
m_flameRange.max = e;
}
if( ImGui::Selectable( ICON_FA_HOURGLASS_HALF " Limit wait stacks range" ) )
{
m_waitStackRange.active = true;

View File

@@ -167,6 +167,7 @@ public:
bool m_showRanges = false;
Range m_statRange;
Range m_flameRange;
Range m_waitStackRange;
private:
@@ -377,6 +378,7 @@ private:
int64_t GetZoneSelfTime( const ZoneEvent& zone );
int64_t GetZoneSelfTime( const GpuEvent& zone );
bool GetZoneRunningTime( const ContextSwitch* ctx, const ZoneEvent& ev, int64_t& time, uint64_t& cnt );
bool GetZoneRunningTime( const ContextSwitch* ctx, const ZoneEvent& ev, const RangeSlim& range, int64_t& time, uint64_t& cnt );
const char* GetThreadContextData( uint64_t thread, bool& local, bool& untracked, const char*& program );
tracy_force_inline void CalcZoneTimeData( unordered_flat_map<int16_t, ZoneTimeData>& data, int64_t& ztime, const ZoneEvent& zone );
@@ -926,6 +928,7 @@ private:
{
uint64_t count = 0;
uint64_t lastTime = 0;
RangeSlim range = {false, 0, 0};
void Reset()
{

View File

@@ -307,6 +307,7 @@ void View::DrawFindZone()
if( ImGui::Button( ICON_FA_BAN " Clear" ) )
{
m_findZone.pattern[0] = '\0';
m_findZone.Reset();
}
ImGui::SameLine();

View File

@@ -27,7 +27,17 @@ void View::BuildFlameGraph( const Worker& worker, std::vector<FlameGraphItem>& d
{
if( !v.IsEndValid() ) break;
const auto srcloc = v.SrcLoc();
const auto duration = v.End() - v.Start();
auto start = v.Start();
auto end = v.End();
if ( m_flameGraphInvariant.range.active )
{
start = std::clamp(start, m_flameGraphInvariant.range.min, m_flameGraphInvariant.range.max);
end = std::clamp(end, m_flameGraphInvariant.range.min, m_flameGraphInvariant.range.max);
}
const auto duration = end - start;
if( srcloc == last )
{
cache->time += duration;
@@ -70,7 +80,17 @@ void View::BuildFlameGraph( const Worker& worker, std::vector<FlameGraphItem>& d
{
if( !v->IsEndValid() ) break;
const auto srcloc = v->SrcLoc();
const auto duration = v->End() - v->Start();
auto start = v->Start();
auto end = v->End();
if ( m_flameGraphInvariant.range.active )
{
start = std::clamp(start, m_flameGraphInvariant.range.min, m_flameGraphInvariant.range.max);
end = std::clamp(end, m_flameGraphInvariant.range.min, m_flameGraphInvariant.range.max);
}
const auto duration = end - start;
if( srcloc == last )
{
cache->time += duration;
@@ -124,7 +144,15 @@ void View::BuildFlameGraph( const Worker& worker, std::vector<FlameGraphItem>& d
const auto srcloc = v.SrcLoc();
int64_t duration;
uint64_t cnt;
if( !GetZoneRunningTime( ctx, v, duration, cnt ) ) break;
if ( m_flameRange.active )
{
if( !GetZoneRunningTime( ctx, v, m_flameGraphInvariant.range, duration, cnt ) ) continue;
}
else
{
if( !GetZoneRunningTime( ctx, v, duration, cnt ) ) break;
}
if( srcloc == last )
{
cache->time += duration;
@@ -169,7 +197,15 @@ void View::BuildFlameGraph( const Worker& worker, std::vector<FlameGraphItem>& d
const auto srcloc = v->SrcLoc();
int64_t duration;
uint64_t cnt;
if( !GetZoneRunningTime( ctx, *v, duration, cnt ) ) break;
if ( m_flameRange.active )
{
if( !GetZoneRunningTime( ctx, *v, m_flameGraphInvariant.range, duration, cnt ) ) continue;
}
else
{
if( !GetZoneRunningTime( ctx, *v, duration, cnt ) ) break;
}
if( srcloc == last )
{
cache->time += duration;
@@ -221,6 +257,15 @@ void View::BuildFlameGraph( const Worker& worker, std::vector<FlameGraphItem>& d
for( auto& v : samples )
{
if ( m_flameGraphInvariant.range.active )
{
if ( v.time.Val() < m_flameGraphInvariant.range.min ||
v.time.Val() > m_flameGraphInvariant.range.max )
{
continue;
}
}
cache.clear();
const auto cs = v.callstack.Val();
@@ -730,6 +775,24 @@ void View::DrawFlameGraph()
if( m_flameExternal ) ImGui::EndDisabled();
}
if( ImGui::Checkbox( "Limit range", &m_flameRange.active ) )
{
if( m_flameRange.active && m_flameRange.min == 0 && m_flameRange.max == 0 )
{
m_flameRange.min = m_vd.zvStart;
m_flameRange.max = m_vd.zvEnd;
}
m_flameGraphInvariant.Reset();
}
if( m_flameRange.active )
{
ImGui::SameLine();
TextColoredUnformatted( 0xFF00FFFF, ICON_FA_TRIANGLE_EXCLAMATION );
ImGui::SameLine();
ToggleButton( ICON_FA_RULER " Limits", m_showRanges );
}
auto& td = m_worker.GetThreadData();
auto expand = ImGui::TreeNode( ICON_FA_SHUFFLE " Visible threads:" );
ImGui::SameLine();
@@ -791,8 +854,11 @@ void View::DrawFlameGraph()
ImGui::PopStyleVar();
if( m_flameMode == 0 && ( m_flameGraphInvariant.count != m_worker.GetZoneCount() || m_flameGraphInvariant.lastTime != m_worker.GetLastTime() ) ||
m_flameMode == 1 && ( m_flameGraphInvariant.count != m_worker.GetCallstackSampleCount() ) )
m_flameMode == 1 && ( m_flameGraphInvariant.count != m_worker.GetCallstackSampleCount() ) ||
m_flameGraphInvariant.range != m_flameRange )
{
m_flameGraphInvariant.range = m_flameRange;
size_t sz = 0;
for( auto& thread : td ) if( FlameGraphThread( thread->id ) ) sz++;

View File

@@ -14,9 +14,11 @@ void View::DrawRanges()
ImGui::Separator();
DrawRangeEntry( m_statRange, ICON_FA_ARROW_UP_WIDE_SHORT " Statistics", 0x448888EE, "RangeStatisticsCopyFrom", 1 );
ImGui::Separator();
DrawRangeEntry( m_waitStackRange, ICON_FA_HOURGLASS_HALF " Wait stacks", 0x44EEB588, "RangeWaitStackCopyFrom", 2 );
DrawRangeEntry( m_flameRange, ICON_FA_FIRE_FLAME_CURVED " Flame", 0x4488B5EE, "RangeFlameCopyFrom", 2 );
ImGui::Separator();
DrawRangeEntry( m_memInfo.range, ICON_FA_MEMORY " Memory", 0x4488EEE3, "RangeMemoryCopyFrom", 3 );
DrawRangeEntry( m_waitStackRange, ICON_FA_HOURGLASS_HALF " Wait stacks", 0x44EEB588, "RangeWaitStackCopyFrom", 3 );
ImGui::Separator();
DrawRangeEntry( m_memInfo.range, ICON_FA_MEMORY " Memory", 0x4488EEE3, "RangeMemoryCopyFrom", 4 );
ImGui::End();
}
@@ -79,9 +81,14 @@ void View::DrawRangeEntry( Range& range, const char* label, uint32_t color, cons
if( id != 2 )
{
ImGui::SameLine();
if( SmallButtonDisablable( ICON_FA_HOURGLASS_HALF " Copy from wait stacks", m_waitStackRange.min == 0 && m_waitStackRange.max == 0 ) ) range = m_waitStackRange;
if( SmallButtonDisablable( ICON_FA_FIRE_FLAME_CURVED " Copy from flame", m_flameRange.min == 0 && m_flameRange.max == 0 ) ) range = m_flameRange;
}
if( id != 3 )
{
ImGui::SameLine();
if( SmallButtonDisablable( ICON_FA_HOURGLASS_HALF " Copy from wait stacks", m_waitStackRange.min == 0 && m_waitStackRange.max == 0 ) ) range = m_waitStackRange;
}
if( id != 4 )
{
ImGui::SameLine();
if( SmallButtonDisablable( ICON_FA_MEMORY " Copy from memory", m_memInfo.range.min == 0 && m_memInfo.range.max == 0 ) ) range = m_memInfo.range;

View File

@@ -254,6 +254,7 @@ void View::DrawTimeline()
m_zoneHover2.Decay( nullptr );
m_findZone.range.StartFrame();
m_statRange.StartFrame();
m_flameRange.StartFrame();
m_waitStackRange.StartFrame();
m_memInfo.range.StartFrame();
m_yDelta = 0;
@@ -283,6 +284,7 @@ void View::DrawTimeline()
{
HandleRange( m_findZone.range, timespan, ImGui::GetCursorScreenPos(), w );
HandleRange( m_statRange, timespan, ImGui::GetCursorScreenPos(), w );
HandleRange( m_flameRange, timespan, ImGui::GetCursorScreenPos(), w );
HandleRange( m_waitStackRange, timespan, ImGui::GetCursorScreenPos(), w );
HandleRange( m_memInfo.range, timespan, ImGui::GetCursorScreenPos(), w );
for( auto& v : m_annotations )
@@ -495,6 +497,15 @@ void View::DrawTimeline()
DrawLine( draw, ImVec2( dpos.x + px1, linepos.y + 0.5f ), ImVec2( dpos.x + px1, linepos.y + lineh + 0.5f ), m_statRange.hiMax ? 0x998888EE : 0x338888EE, m_statRange.hiMax ? 2 : 1 );
}
if( m_flameRange.active && ( m_showFlameGraph || m_showRanges ) )
{
const auto px0 = ( m_flameRange.min - m_vd.zvStart ) * pxns;
const auto px1 = std::max( px0 + std::max( 1.0, pxns * 0.5 ), ( m_flameRange.max - m_vd.zvStart ) * pxns );
DrawStripedRect( draw, wpos, px0, linepos.y, px1, linepos.y + lineh, 10 * scale, 0x2288B5EE, true, false );
DrawLine( draw, ImVec2( dpos.x + px0, linepos.y + 0.5f ), ImVec2( dpos.x + px0, linepos.y + lineh + 0.5f ), m_flameRange.hiMin ? 0x9988B5EE : 0x3388B5EE, m_flameRange.hiMin ? 2 : 1 );
DrawLine( draw, ImVec2( dpos.x + px1, linepos.y + 0.5f ), ImVec2( dpos.x + px1, linepos.y + lineh + 0.5f ), m_flameRange.hiMax ? 0x9988B5EE : 0x3388B5EE, m_flameRange.hiMax ? 2 : 1 );
}
if( m_waitStackRange.active && ( m_showWaitStacks || m_showRanges ) )
{
const auto px0 = ( m_waitStackRange.min - m_vd.zvStart ) * pxns;

View File

@@ -737,6 +737,35 @@ bool View::GetZoneRunningTime( const ContextSwitch* ctx, const ZoneEvent& ev, in
return true;
}
bool View::GetZoneRunningTime( const ContextSwitch* ctx, const ZoneEvent& ev, const RangeSlim& range, int64_t& time, uint64_t& cnt )
{
const auto start = std::max( ev.Start(), range.min );
auto it = std::lower_bound( ctx->v.begin(), ctx->v.end(), start, [] ( const auto& l, const auto& r ) { return (uint64_t)l.End() < (uint64_t)r; } );
if( it == ctx->v.end() ) return false;
const auto end = std::min( m_worker.GetZoneEnd( ev ), range.max );
const auto eit = std::upper_bound( it, ctx->v.end(), end, [] ( const auto& l, const auto& r ) { return l < r.Start(); } );
if( eit == ctx->v.end() ) return false;
cnt = std::distance( it, eit );
if( cnt == 0 ) return false;
if( cnt == 1 )
{
time = end - start;
}
else
{
int64_t running = it->End() - start;
++it;
for( uint64_t i=0; i<cnt-2; i++ )
{
running += it->End() - it->Start();
++it;
}
running += end - it->Start();
time = running;
}
return true;
}
const char* View::SourceSubstitution( const char* srcFile ) const
{
if( !m_sourceRegexValid || m_sourceSubstitutions.empty() ) return srcFile;

View File

@@ -10,6 +10,9 @@
# include <inttypes.h>
# include <intrin.h>
# include "../common/TracyUwp.hpp"
# ifndef _MSC_VER
# include <excpt.h>
# endif
#else
# include <sys/time.h>
# include <sys/param.h>
@@ -909,6 +912,13 @@ LONG WINAPI CrashFilter( PEXCEPTION_POINTERS pExp )
}
#endif
#if defined _WIN32 && !defined _MSC_VER
LONG WINAPI CrashFilterExecute( PEXCEPTION_POINTERS pExp )
{
return EXCEPTION_EXECUTE_HANDLER;
}
#endif
static Profiler* s_instance = nullptr;
static Thread* s_thread;
#ifndef TRACY_NO_FRAME_IMAGE
@@ -1511,7 +1521,7 @@ void Profiler::InstallCrashHandler()
#if defined _WIN32 && !defined TRACY_UWP && !defined TRACY_NO_CRASH_HANDLER
// We cannot use Vectored Exception handling because it catches application-wide frame-based SEH blocks. We only
// want to catch unhandled exceptions.
m_prevHandler = SetUnhandledExceptionFilter( CrashFilter );
m_prevHandler = reinterpret_cast<void*>( SetUnhandledExceptionFilter( CrashFilter ) );
#endif
#ifndef TRACY_NO_CRASH_HANDLER
@@ -3122,6 +3132,7 @@ char* Profiler::SafeCopyProlog( const char* data, size_t size )
if( size > SafeSendBufferSize ) buf = (char*)tracy_malloc( size );
#ifdef _WIN32
# ifdef _MSC_VER
__try
{
memcpy( buf, data, size );
@@ -3130,6 +3141,9 @@ char* Profiler::SafeCopyProlog( const char* data, size_t size )
{
success = false;
}
# else
memcpy( buf, data, size );
# endif
#else
// Send through the pipe to ensure safe reads
for( size_t offset = 0; offset != size; /*in loop*/ )

View File

@@ -7,7 +7,7 @@ namespace Version
{
enum { Major = 0 };
enum { Minor = 12 };
enum { Patch = 0 };
enum { Patch = 2 };
}
}

View File

@@ -145,6 +145,13 @@ TRACY_API LuaZoneState& GetLuaZoneState();
namespace detail
{
static inline void LuaShortenSrc( char* dst, const char* src )
{
size_t l = std::min( (size_t)255, strlen( src ) );
memcpy( dst, src, l );
dst[l] = 0;
}
#ifdef TRACY_HAS_CALLSTACK
static tracy_force_inline void SendLuaCallstack( lua_State* L, uint32_t depth )
{
@@ -190,13 +197,6 @@ static tracy_force_inline void SendLuaCallstack( lua_State* L, uint32_t depth )
TracyQueueCommit( callstackAllocFatThread );
}
static inline void LuaShortenSrc( char* dst, const char* src )
{
size_t l = std::min( (size_t)255, strlen( src ) );
memcpy( dst, src, l );
dst[l] = 0;
}
static inline int LuaZoneBeginS( lua_State* L )
{
#ifdef TRACY_ON_DEMAND

View File

@@ -1,7 +1,8 @@
cmake_minimum_required(VERSION 3.16)
option(NO_ISA_EXTENSIONS "Disable ISA extensions (don't pass -march=native or -mcpu=native to the compiler)" OFF)
option(NO_STATISTICS "Disable calculation of statistics" ON)
set(NO_STATISTICS ON)
include(${CMAKE_CURRENT_LIST_DIR}/../cmake/version.cmake)

View File

@@ -15,7 +15,7 @@ bool ApplyPathSubstitutions( std::string& path, const PathSubstitutionList& path
{
for( const auto& substitution : pathSubstitutionlist )
{
if( std::regex_match(path, substitution.first) )
if( std::regex_search(path, substitution.first) )
{
path = std::regex_replace( path, substitution.first, substitution.second );
return true;
@@ -168,4 +168,4 @@ void PatchSymbols( tracy::Worker& worker, const std::vector<std::string>& pathSu
{
std::cerr << "Failed to patch symbols" << std::endl;
}
}
}

View File

@@ -89,7 +89,7 @@ public:
const size_t startIdx = entryIdx;
const size_t batchEndIdx = std::min( inputEntryList.size(), startIdx + (size_t)1024 );
printf( "Resolving symbols [%zu-%zu[\n", startIdx, batchEndIdx );
printf( "Resolving symbols [%zu-%zu]\n", startIdx, batchEndIdx );
// generate a single addr2line cmd line for all addresses in one invocation
std::stringstream ss;