mirror of
https://github.com/wolfpld/tracy.git
synced 2024-11-22 22:44:34 +00:00
Parallelize building flame graph.
This commit is contained in:
parent
da1e92956f
commit
20c4822c98
@ -56,6 +56,11 @@ View::View( void(*cbMainThread)(const std::function<void()>&, bool), const char*
|
|||||||
, m_cbMainThread( cbMainThread )
|
, m_cbMainThread( cbMainThread )
|
||||||
, m_achievementsMgr( amgr )
|
, m_achievementsMgr( amgr )
|
||||||
, m_achievements( config.achievements )
|
, m_achievements( config.achievements )
|
||||||
|
#ifdef __EMSCRIPTEN__
|
||||||
|
, m_td( 2, "ViewMt" )
|
||||||
|
#else
|
||||||
|
, m_td( std::thread::hardware_concurrency(), "ViewMt" )
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
InitTextEditor();
|
InitTextEditor();
|
||||||
SetupConfig( config );
|
SetupConfig( config );
|
||||||
@ -80,6 +85,11 @@ View::View( void(*cbMainThread)(const std::function<void()>&, bool), FileRead& f
|
|||||||
, m_cbMainThread( cbMainThread )
|
, m_cbMainThread( cbMainThread )
|
||||||
, m_achievementsMgr( amgr )
|
, m_achievementsMgr( amgr )
|
||||||
, m_achievements( config.achievements )
|
, m_achievements( config.achievements )
|
||||||
|
#ifdef __EMSCRIPTEN__
|
||||||
|
, m_td( 2, "ViewMt" )
|
||||||
|
#else
|
||||||
|
, m_td( std::thread::hardware_concurrency(), "ViewMt" )
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
m_notificationTime = 4;
|
m_notificationTime = 4;
|
||||||
m_notificationText = std::string( "Trace loaded in " ) + TimeToString( m_worker.GetLoadTime() );
|
m_notificationText = std::string( "Trace loaded in " ) + TimeToString( m_worker.GetLoadTime() );
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
#include "TracyUtility.hpp"
|
#include "TracyUtility.hpp"
|
||||||
#include "TracyViewData.hpp"
|
#include "TracyViewData.hpp"
|
||||||
#include "../server/TracyFileWrite.hpp"
|
#include "../server/TracyFileWrite.hpp"
|
||||||
|
#include "../server/TracyTaskDispatch.hpp"
|
||||||
#include "../server/TracyShortPtr.hpp"
|
#include "../server/TracyShortPtr.hpp"
|
||||||
#include "../server/TracyWorker.hpp"
|
#include "../server/TracyWorker.hpp"
|
||||||
#include "../server/tracy_robin_hood.h"
|
#include "../server/tracy_robin_hood.h"
|
||||||
@ -277,9 +278,9 @@ private:
|
|||||||
void DrawFlameGraph();
|
void DrawFlameGraph();
|
||||||
void DrawFlameGraphHeader( uint64_t timespan );
|
void DrawFlameGraphHeader( uint64_t timespan );
|
||||||
void DrawFlameGraphItem( const FlameGraphItem& item, FlameGraphContext& ctx, uint64_t ts, int depth, bool samples );
|
void DrawFlameGraphItem( const FlameGraphItem& item, FlameGraphContext& ctx, uint64_t ts, int depth, bool samples );
|
||||||
void BuildFlameGraph( const Worker& worker, Vector<FlameGraphItem>& data, const Vector<short_ptr<ZoneEvent>>& zones );
|
void BuildFlameGraph( const Worker& worker, std::vector<FlameGraphItem>& data, const Vector<short_ptr<ZoneEvent>>& zones );
|
||||||
void BuildFlameGraph( const Worker& worker, Vector<FlameGraphItem>& data, const Vector<short_ptr<ZoneEvent>>& zones, const ContextSwitch* ctx );
|
void BuildFlameGraph( const Worker& worker, std::vector<FlameGraphItem>& data, const Vector<short_ptr<ZoneEvent>>& zones, const ContextSwitch* ctx );
|
||||||
void BuildFlameGraph( const Worker& worker, Vector<FlameGraphItem>& data, const Vector<SampleData>& samples );
|
void BuildFlameGraph( const Worker& worker, std::vector<FlameGraphItem>& data, const Vector<SampleData>& samples );
|
||||||
|
|
||||||
void ListMemData( std::vector<const MemEvent*>& vec, const std::function<void(const MemEvent*)>& DrawAddress, int64_t startTime = -1, uint64_t pool = 0 );
|
void ListMemData( std::vector<const MemEvent*>& vec, const std::function<void(const MemEvent*)>& DrawAddress, int64_t startTime = -1, uint64_t pool = 0 );
|
||||||
|
|
||||||
@ -899,6 +900,8 @@ private:
|
|||||||
|
|
||||||
AchievementsMgr* m_achievementsMgr;
|
AchievementsMgr* m_achievementsMgr;
|
||||||
bool m_achievements = false;
|
bool m_achievements = false;
|
||||||
|
|
||||||
|
TaskDispatch m_td;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -17,12 +17,12 @@ struct FlameGraphItem
|
|||||||
{
|
{
|
||||||
int64_t srcloc;
|
int64_t srcloc;
|
||||||
int64_t time;
|
int64_t time;
|
||||||
Vector<FlameGraphItem> children;
|
std::vector<FlameGraphItem> children;
|
||||||
};
|
};
|
||||||
|
|
||||||
void View::BuildFlameGraph( const Worker& worker, Vector<FlameGraphItem>& data, const Vector<short_ptr<ZoneEvent>>& zones )
|
void View::BuildFlameGraph( const Worker& worker, std::vector<FlameGraphItem>& data, const Vector<short_ptr<ZoneEvent>>& zones )
|
||||||
{
|
{
|
||||||
FlameGraphItem* it;
|
FlameGraphItem* cache;
|
||||||
int16_t last = 0;
|
int16_t last = 0;
|
||||||
|
|
||||||
if( zones.is_magic() )
|
if( zones.is_magic() )
|
||||||
@ -35,25 +35,25 @@ void View::BuildFlameGraph( const Worker& worker, Vector<FlameGraphItem>& data,
|
|||||||
const auto duration = v.End() - v.Start();
|
const auto duration = v.End() - v.Start();
|
||||||
if( srcloc == last )
|
if( srcloc == last )
|
||||||
{
|
{
|
||||||
it->time += duration;
|
cache->time += duration;
|
||||||
if( v.HasChildren() )
|
if( v.HasChildren() )
|
||||||
{
|
{
|
||||||
auto& children = worker.GetZoneChildren( v.Child() );
|
auto& children = worker.GetZoneChildren( v.Child() );
|
||||||
BuildFlameGraph( worker, it->children, children );
|
BuildFlameGraph( worker, cache->children, children );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
it = std::find_if( data.begin(), data.end(), [srcloc]( const auto& v ) { return v.srcloc == srcloc; } );
|
auto it = std::find_if( data.begin(), data.end(), [srcloc]( const auto& v ) { return v.srcloc == srcloc; } );
|
||||||
if( it == data.end() )
|
if( it == data.end() )
|
||||||
{
|
{
|
||||||
data.push_back( FlameGraphItem { srcloc, duration } );
|
data.emplace_back( FlameGraphItem { srcloc, duration } );
|
||||||
if( v.HasChildren() )
|
if( v.HasChildren() )
|
||||||
{
|
{
|
||||||
auto& children = worker.GetZoneChildren( v.Child() );
|
auto& children = worker.GetZoneChildren( v.Child() );
|
||||||
BuildFlameGraph( worker, data.back().children, children );
|
BuildFlameGraph( worker, data.back().children, children );
|
||||||
}
|
}
|
||||||
it = &data.back();
|
cache = &data.back();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -63,6 +63,7 @@ void View::BuildFlameGraph( const Worker& worker, Vector<FlameGraphItem>& data,
|
|||||||
auto& children = worker.GetZoneChildren( v.Child() );
|
auto& children = worker.GetZoneChildren( v.Child() );
|
||||||
BuildFlameGraph( worker, it->children, children );
|
BuildFlameGraph( worker, it->children, children );
|
||||||
}
|
}
|
||||||
|
cache = &*it;
|
||||||
}
|
}
|
||||||
last = srcloc;
|
last = srcloc;
|
||||||
}
|
}
|
||||||
@ -77,25 +78,25 @@ void View::BuildFlameGraph( const Worker& worker, Vector<FlameGraphItem>& data,
|
|||||||
const auto duration = v->End() - v->Start();
|
const auto duration = v->End() - v->Start();
|
||||||
if( srcloc == last )
|
if( srcloc == last )
|
||||||
{
|
{
|
||||||
it->time += duration;
|
cache->time += duration;
|
||||||
if( v->HasChildren() )
|
if( v->HasChildren() )
|
||||||
{
|
{
|
||||||
auto& children = worker.GetZoneChildren( v->Child() );
|
auto& children = worker.GetZoneChildren( v->Child() );
|
||||||
BuildFlameGraph( worker, it->children, children );
|
BuildFlameGraph( worker, cache->children, children );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
it = std::find_if( data.begin(), data.end(), [srcloc]( const auto& v ) { return v.srcloc == srcloc; } );
|
auto it = std::find_if( data.begin(), data.end(), [srcloc]( const auto& v ) { return v.srcloc == srcloc; } );
|
||||||
if( it == data.end() )
|
if( it == data.end() )
|
||||||
{
|
{
|
||||||
data.push_back( FlameGraphItem { srcloc, duration } );
|
data.emplace_back( FlameGraphItem { srcloc, duration } );
|
||||||
if( v->HasChildren() )
|
if( v->HasChildren() )
|
||||||
{
|
{
|
||||||
auto& children = worker.GetZoneChildren( v->Child() );
|
auto& children = worker.GetZoneChildren( v->Child() );
|
||||||
BuildFlameGraph( worker, data.back().children, children );
|
BuildFlameGraph( worker, data.back().children, children );
|
||||||
}
|
}
|
||||||
it = &data.back();
|
cache = &data.back();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -105,6 +106,7 @@ void View::BuildFlameGraph( const Worker& worker, Vector<FlameGraphItem>& data,
|
|||||||
auto& children = worker.GetZoneChildren( v->Child() );
|
auto& children = worker.GetZoneChildren( v->Child() );
|
||||||
BuildFlameGraph( worker, it->children, children );
|
BuildFlameGraph( worker, it->children, children );
|
||||||
}
|
}
|
||||||
|
cache = &*it;
|
||||||
}
|
}
|
||||||
last = srcloc;
|
last = srcloc;
|
||||||
}
|
}
|
||||||
@ -112,10 +114,10 @@ void View::BuildFlameGraph( const Worker& worker, Vector<FlameGraphItem>& data,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void View::BuildFlameGraph( const Worker& worker, Vector<FlameGraphItem>& data, const Vector<short_ptr<ZoneEvent>>& zones, const ContextSwitch* ctx )
|
void View::BuildFlameGraph( const Worker& worker, std::vector<FlameGraphItem>& data, const Vector<short_ptr<ZoneEvent>>& zones, const ContextSwitch* ctx )
|
||||||
{
|
{
|
||||||
assert( ctx );
|
assert( ctx );
|
||||||
FlameGraphItem* it;
|
FlameGraphItem* cache;
|
||||||
int16_t last = 0;
|
int16_t last = 0;
|
||||||
|
|
||||||
if( zones.is_magic() )
|
if( zones.is_magic() )
|
||||||
@ -130,25 +132,25 @@ void View::BuildFlameGraph( const Worker& worker, Vector<FlameGraphItem>& data,
|
|||||||
if( !GetZoneRunningTime( ctx, v, duration, cnt ) ) break;
|
if( !GetZoneRunningTime( ctx, v, duration, cnt ) ) break;
|
||||||
if( srcloc == last )
|
if( srcloc == last )
|
||||||
{
|
{
|
||||||
it->time += duration;
|
cache->time += duration;
|
||||||
if( v.HasChildren() )
|
if( v.HasChildren() )
|
||||||
{
|
{
|
||||||
auto& children = worker.GetZoneChildren( v.Child() );
|
auto& children = worker.GetZoneChildren( v.Child() );
|
||||||
BuildFlameGraph( worker, it->children, children, ctx );
|
BuildFlameGraph( worker, cache->children, children, ctx );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
it = std::find_if( data.begin(), data.end(), [srcloc]( const auto& v ) { return v.srcloc == srcloc; } );
|
auto it = std::find_if( data.begin(), data.end(), [srcloc]( const auto& v ) { return v.srcloc == srcloc; } );
|
||||||
if( it == data.end() )
|
if( it == data.end() )
|
||||||
{
|
{
|
||||||
data.push_back( FlameGraphItem { srcloc, duration } );
|
data.emplace_back( FlameGraphItem { srcloc, duration } );
|
||||||
if( v.HasChildren() )
|
if( v.HasChildren() )
|
||||||
{
|
{
|
||||||
auto& children = worker.GetZoneChildren( v.Child() );
|
auto& children = worker.GetZoneChildren( v.Child() );
|
||||||
BuildFlameGraph( worker, data.back().children, children, ctx );
|
BuildFlameGraph( worker, data.back().children, children, ctx );
|
||||||
}
|
}
|
||||||
it = &data.back();
|
cache = &data.back();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -158,6 +160,7 @@ void View::BuildFlameGraph( const Worker& worker, Vector<FlameGraphItem>& data,
|
|||||||
auto& children = worker.GetZoneChildren( v.Child() );
|
auto& children = worker.GetZoneChildren( v.Child() );
|
||||||
BuildFlameGraph( worker, it->children, children, ctx );
|
BuildFlameGraph( worker, it->children, children, ctx );
|
||||||
}
|
}
|
||||||
|
cache = &*it;
|
||||||
}
|
}
|
||||||
last = srcloc;
|
last = srcloc;
|
||||||
}
|
}
|
||||||
@ -174,25 +177,25 @@ void View::BuildFlameGraph( const Worker& worker, Vector<FlameGraphItem>& data,
|
|||||||
if( !GetZoneRunningTime( ctx, *v, duration, cnt ) ) break;
|
if( !GetZoneRunningTime( ctx, *v, duration, cnt ) ) break;
|
||||||
if( srcloc == last )
|
if( srcloc == last )
|
||||||
{
|
{
|
||||||
it->time += duration;
|
cache->time += duration;
|
||||||
if( v->HasChildren() )
|
if( v->HasChildren() )
|
||||||
{
|
{
|
||||||
auto& children = worker.GetZoneChildren( v->Child() );
|
auto& children = worker.GetZoneChildren( v->Child() );
|
||||||
BuildFlameGraph( worker, it->children, children, ctx );
|
BuildFlameGraph( worker, cache->children, children, ctx );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
it = std::find_if( data.begin(), data.end(), [srcloc]( const auto& v ) { return v.srcloc == srcloc; } );
|
auto it = std::find_if( data.begin(), data.end(), [srcloc]( const auto& v ) { return v.srcloc == srcloc; } );
|
||||||
if( it == data.end() )
|
if( it == data.end() )
|
||||||
{
|
{
|
||||||
data.push_back( FlameGraphItem { srcloc, duration } );
|
data.emplace_back( FlameGraphItem { srcloc, duration } );
|
||||||
if( v->HasChildren() )
|
if( v->HasChildren() )
|
||||||
{
|
{
|
||||||
auto& children = worker.GetZoneChildren( v->Child() );
|
auto& children = worker.GetZoneChildren( v->Child() );
|
||||||
BuildFlameGraph( worker, data.back().children, children, ctx );
|
BuildFlameGraph( worker, data.back().children, children, ctx );
|
||||||
}
|
}
|
||||||
it = &data.back();
|
cache = &data.back();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -202,6 +205,7 @@ void View::BuildFlameGraph( const Worker& worker, Vector<FlameGraphItem>& data,
|
|||||||
auto& children = worker.GetZoneChildren( v->Child() );
|
auto& children = worker.GetZoneChildren( v->Child() );
|
||||||
BuildFlameGraph( worker, it->children, children, ctx );
|
BuildFlameGraph( worker, it->children, children, ctx );
|
||||||
}
|
}
|
||||||
|
cache = &*it;
|
||||||
}
|
}
|
||||||
last = srcloc;
|
last = srcloc;
|
||||||
}
|
}
|
||||||
@ -209,7 +213,7 @@ void View::BuildFlameGraph( const Worker& worker, Vector<FlameGraphItem>& data,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void View::BuildFlameGraph( const Worker& worker, Vector<FlameGraphItem>& data, const Vector<SampleData>& samples )
|
void View::BuildFlameGraph( const Worker& worker, std::vector<FlameGraphItem>& data, const Vector<SampleData>& samples )
|
||||||
{
|
{
|
||||||
for( auto& v : samples )
|
for( auto& v : samples )
|
||||||
{
|
{
|
||||||
@ -232,7 +236,7 @@ void View::BuildFlameGraph( const Worker& worker, Vector<FlameGraphItem>& data,
|
|||||||
auto it = std::find_if( vec->begin(), vec->end(), [symaddr]( const auto& v ) { return v.srcloc == symaddr; } );
|
auto it = std::find_if( vec->begin(), vec->end(), [symaddr]( const auto& v ) { return v.srcloc == symaddr; } );
|
||||||
if( it == vec->end() )
|
if( it == vec->end() )
|
||||||
{
|
{
|
||||||
vec->push_back( FlameGraphItem { (int64_t)symaddr, 1 } );
|
vec->emplace_back( FlameGraphItem { (int64_t)symaddr, 1 } );
|
||||||
vec = &vec->back().children;
|
vec = &vec->back().children;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -247,21 +251,12 @@ void View::BuildFlameGraph( const Worker& worker, Vector<FlameGraphItem>& data,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void SortFlameGraph( Vector<FlameGraphItem>& data )
|
static void SortFlameGraph( std::vector<FlameGraphItem>& data )
|
||||||
{
|
{
|
||||||
pdqsort_branchless( data.begin(), data.end(), []( const FlameGraphItem& lhs, const FlameGraphItem& rhs ) { return lhs.time > rhs.time; } );
|
pdqsort_branchless( data.begin(), data.end(), []( const FlameGraphItem& lhs, const FlameGraphItem& rhs ) { return lhs.time > rhs.time; } );
|
||||||
for( auto& v : data ) SortFlameGraph( v.children );
|
for( auto& v : data ) SortFlameGraph( v.children );
|
||||||
}
|
}
|
||||||
|
|
||||||
static void FreeVector( Vector<FlameGraphItem>& data )
|
|
||||||
{
|
|
||||||
for( auto& v : data )
|
|
||||||
{
|
|
||||||
FreeVector( v.children );
|
|
||||||
v.children.~Vector();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct FlameGraphContext
|
struct FlameGraphContext
|
||||||
{
|
{
|
||||||
ImDrawList* draw;
|
ImDrawList* draw;
|
||||||
@ -521,6 +516,23 @@ void View::DrawFlameGraphHeader( uint64_t timespan )
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void MergeFlameGraph( std::vector<FlameGraphItem>& dst, std::vector<FlameGraphItem>&& src )
|
||||||
|
{
|
||||||
|
for( auto& v : src )
|
||||||
|
{
|
||||||
|
auto it = std::find_if( dst.begin(), dst.end(), [&v]( const auto& vv ) { return vv.srcloc == v.srcloc; } );
|
||||||
|
if( it == dst.end() )
|
||||||
|
{
|
||||||
|
dst.emplace_back( std::move( v ) );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
it->time += v.time;
|
||||||
|
MergeFlameGraph( it->children, std::move( v.children ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void View::DrawFlameGraph()
|
void View::DrawFlameGraph()
|
||||||
{
|
{
|
||||||
const auto scale = GetScale();
|
const auto scale = GetScale();
|
||||||
@ -613,8 +625,13 @@ void View::DrawFlameGraph()
|
|||||||
ImGui::Separator();
|
ImGui::Separator();
|
||||||
ImGui::PopStyleVar();
|
ImGui::PopStyleVar();
|
||||||
|
|
||||||
Vector<FlameGraphItem> data;
|
size_t sz = 0;
|
||||||
|
for( auto& thread : m_threadOrder ) if( FlameGraphThread( thread->id ) ) sz++;
|
||||||
|
|
||||||
|
std::vector<std::vector<FlameGraphItem>> threadData;
|
||||||
|
threadData.resize( sz );
|
||||||
|
|
||||||
|
size_t idx = 0;
|
||||||
if( m_flameMode == 0 )
|
if( m_flameMode == 0 )
|
||||||
{
|
{
|
||||||
for( auto& thread : m_worker.GetThreadData() )
|
for( auto& thread : m_worker.GetThreadData() )
|
||||||
@ -624,12 +641,20 @@ void View::DrawFlameGraph()
|
|||||||
if( m_flameRunningTime )
|
if( m_flameRunningTime )
|
||||||
{
|
{
|
||||||
const auto ctx = m_worker.GetContextSwitchData( thread->id );
|
const auto ctx = m_worker.GetContextSwitchData( thread->id );
|
||||||
if( ctx ) BuildFlameGraph( m_worker, data, thread->timeline, ctx );
|
if( ctx )
|
||||||
|
{
|
||||||
|
m_td.Queue( [this, idx, ctx, thread, &threadData] {
|
||||||
|
BuildFlameGraph( m_worker, threadData[idx], thread->timeline, ctx );
|
||||||
|
} );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
BuildFlameGraph( m_worker, data, thread->timeline );
|
m_td.Queue( [this, idx, thread, &threadData] {
|
||||||
|
BuildFlameGraph( m_worker, threadData[idx], thread->timeline );
|
||||||
|
} );
|
||||||
}
|
}
|
||||||
|
idx++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -637,7 +662,24 @@ void View::DrawFlameGraph()
|
|||||||
{
|
{
|
||||||
for( auto& thread : m_worker.GetThreadData() )
|
for( auto& thread : m_worker.GetThreadData() )
|
||||||
{
|
{
|
||||||
if( FlameGraphThread( thread->id ) ) BuildFlameGraph( m_worker, data, thread->samples );
|
if( FlameGraphThread( thread->id ) )
|
||||||
|
{
|
||||||
|
m_td.Queue( [this, idx, thread, &threadData] {
|
||||||
|
BuildFlameGraph( m_worker, threadData[idx], thread->samples );
|
||||||
|
} );
|
||||||
|
idx++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m_td.Sync();
|
||||||
|
|
||||||
|
std::vector<FlameGraphItem> data;
|
||||||
|
if( !threadData.empty() )
|
||||||
|
{
|
||||||
|
std::swap( data, threadData[0] );
|
||||||
|
for( size_t i=1; i<threadData.size(); i++ )
|
||||||
|
{
|
||||||
|
MergeFlameGraph( data, std::move( threadData[i] ) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -682,7 +724,6 @@ void View::DrawFlameGraph()
|
|||||||
ImGui::EndChild();
|
ImGui::EndChild();
|
||||||
|
|
||||||
ImGui::End();
|
ImGui::End();
|
||||||
FreeVector( data );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user