Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/wolfpld/tracy.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBartosz Taudul <wolf@nereid.pl>2022-07-02 15:40:00 +0300
committerBartosz Taudul <wolf@nereid.pl>2022-07-02 15:42:06 +0300
commitde5c4c678a9ffe4eb28fb45198f8459ac607e829 (patch)
tree6d2460c9982cd91fcdeb3d69552ae060e8459cd4 /server/TracyView.cpp
parentf3fe8b27e8ea1b314930fda68609aeba2ba31cce (diff)
Extract memory UI from View.
Diffstat (limited to 'server/TracyView.cpp')
-rw-r--r--server/TracyView.cpp891
1 files changed, 0 insertions, 891 deletions
diff --git a/server/TracyView.cpp b/server/TracyView.cpp
index d5aeaf07..b938b617 100644
--- a/server/TracyView.cpp
+++ b/server/TracyView.cpp
@@ -6314,148 +6314,6 @@ void View::DrawSamplesStatistics( Vector<SymList>& data, int64_t timeRange, Accu
}
}
-void View::DrawMemoryAllocWindow()
-{
- bool show = true;
- ImGui::Begin( "Memory allocation", &show, ImGuiWindowFlags_AlwaysAutoResize );
- if( !ImGui::GetCurrentWindowRead()->SkipItems )
- {
- const auto& mem = m_worker.GetMemoryNamed( m_memoryAllocInfoPool );
- const auto& ev = mem.data[m_memoryAllocInfoWindow];
- const auto tidAlloc = m_worker.DecompressThread( ev.ThreadAlloc() );
- const auto tidFree = m_worker.DecompressThread( ev.ThreadFree() );
- int idx = 0;
-
- if( ImGui::Button( ICON_FA_MICROSCOPE " Zoom to allocation" ) )
- {
- ZoomToRange( ev.TimeAlloc(), ev.TimeFree() >= 0 ? ev.TimeFree() : m_worker.GetLastTime() );
- }
-
- if( m_worker.GetMemNameMap().size() > 1 )
- {
- TextFocused( ICON_FA_ARCHIVE " Pool:", m_memoryAllocInfoPool == 0 ? "Default allocator" : m_worker.GetString( m_memoryAllocInfoPool ) );
- }
- char buf[64];
- sprintf( buf, "0x%" PRIx64, ev.Ptr() );
- TextFocused( "Address:", buf );
- TextFocused( "Size:", MemSizeToString( ev.Size() ) );
- if( ev.Size() >= 10000ll )
- {
- ImGui::SameLine();
- ImGui::TextDisabled( "(%s bytes)", RealToString( ev.Size() ) );
- }
- ImGui::Separator();
- TextFocused( "Appeared at", TimeToStringExact( ev.TimeAlloc() ) );
- if( ImGui::IsItemClicked() ) CenterAtTime( ev.TimeAlloc() );
- ImGui::SameLine(); ImGui::Spacing(); ImGui::SameLine();
- SmallColorBox( GetThreadColor( tidAlloc, 0 ) );
- ImGui::SameLine();
- TextFocused( "Thread:", m_worker.GetThreadName( tidAlloc ) );
- ImGui::SameLine();
- ImGui::TextDisabled( "(%s)", RealToString( tidAlloc ) );
- if( m_worker.IsThreadFiber( tidAlloc ) )
- {
- ImGui::SameLine();
- TextColoredUnformatted( ImVec4( 0.2f, 0.6f, 0.2f, 1.f ), "Fiber" );
- }
- if( ev.CsAlloc() != 0 )
- {
- const auto cs = ev.CsAlloc();
- SmallCallstackButton( ICON_FA_ALIGN_JUSTIFY, cs, idx );
- ImGui::SameLine();
- DrawCallstackCalls( cs, 2 );
- }
- if( ev.TimeFree() < 0 )
- {
- TextDisabledUnformatted( "Allocation still active" );
- }
- else
- {
- TextFocused( "Freed at", TimeToStringExact( ev.TimeFree() ) );
- if( ImGui::IsItemClicked() ) CenterAtTime( ev.TimeFree() );
- ImGui::SameLine(); ImGui::Spacing(); ImGui::SameLine();
- SmallColorBox( GetThreadColor( tidFree, 0 ) );
- ImGui::SameLine();
- TextFocused( "Thread:", m_worker.GetThreadName( tidFree ) );
- ImGui::SameLine();
- ImGui::TextDisabled( "(%s)", RealToString( tidFree ) );
- if( m_worker.IsThreadFiber( tidFree ) )
- {
- ImGui::SameLine();
- TextColoredUnformatted( ImVec4( 0.2f, 0.6f, 0.2f, 1.f ), "Fiber" );
- }
- if( ev.csFree.Val() != 0 )
- {
- const auto cs = ev.csFree.Val();
- SmallCallstackButton( ICON_FA_ALIGN_JUSTIFY, cs, idx );
- ImGui::SameLine();
- DrawCallstackCalls( cs, 2 );
- }
- TextFocused( "Duration:", TimeToString( ev.TimeFree() - ev.TimeAlloc() ) );
- }
-
- bool sep = false;
- auto zoneAlloc = FindZoneAtTime( tidAlloc, ev.TimeAlloc() );
- if( zoneAlloc )
- {
- ImGui::Separator();
- sep = true;
- const auto& srcloc = m_worker.GetSourceLocation( zoneAlloc->SrcLoc() );
- const auto txt = srcloc.name.active ? m_worker.GetString( srcloc.name ) : m_worker.GetString( srcloc.function );
- ImGui::PushID( idx++ );
- TextFocused( "Zone alloc:", txt );
- auto hover = ImGui::IsItemHovered();
- ImGui::PopID();
- if( ImGui::IsItemClicked() )
- {
- ShowZoneInfo( *zoneAlloc );
- }
- if( hover )
- {
- m_zoneHighlight = zoneAlloc;
- if( IsMouseClicked( 2 ) )
- {
- ZoomToZone( *zoneAlloc );
- }
- ZoneTooltip( *zoneAlloc );
- }
- }
-
- if( ev.TimeFree() >= 0 )
- {
- auto zoneFree = FindZoneAtTime( tidFree, ev.TimeFree() );
- if( zoneFree )
- {
- if( !sep ) ImGui::Separator();
- const auto& srcloc = m_worker.GetSourceLocation( zoneFree->SrcLoc() );
- const auto txt = srcloc.name.active ? m_worker.GetString( srcloc.name ) : m_worker.GetString( srcloc.function );
- TextFocused( "Zone free:", txt );
- auto hover = ImGui::IsItemHovered();
- if( ImGui::IsItemClicked() )
- {
- ShowZoneInfo( *zoneFree );
- }
- if( hover )
- {
- m_zoneHighlight = zoneFree;
- if( IsMouseClicked( 2 ) )
- {
- ZoomToZone( *zoneFree );
- }
- ZoneTooltip( *zoneFree );
- }
- if( zoneAlloc != 0 && zoneAlloc == zoneFree )
- {
- ImGui::SameLine();
- TextDisabledUnformatted( "(same zone)" );
- }
- }
- }
- }
- ImGui::End();
- if( !show ) m_memoryAllocInfoWindow = -1;
-}
-
void View::DrawTextEditor()
{
const auto scale = GetScale();
@@ -7461,254 +7319,6 @@ void View::DrawWaitStacks()
ImGui::End();
}
-void View::ListMemData( std::vector<const MemEvent*>& vec, std::function<void(const MemEvent*)> DrawAddress, const char* id, int64_t startTime, uint64_t pool )
-{
- if( startTime == -1 ) startTime = 0;
- if( ImGui::BeginTable( "##mem", 8, ImGuiTableFlags_Resizable | ImGuiTableFlags_Reorderable | ImGuiTableFlags_Hideable | ImGuiTableFlags_Sortable | ImGuiTableFlags_BordersInnerV | ImGuiTableFlags_ScrollY, ImVec2( 0, ImGui::GetTextLineHeightWithSpacing() * std::min<int64_t>( 1+vec.size(), 15 ) ) ) )
- {
- ImGui::TableSetupScrollFreeze( 0, 1 );
- ImGui::TableSetupColumn( "Address", ImGuiTableColumnFlags_NoHide );
- ImGui::TableSetupColumn( "Size", ImGuiTableColumnFlags_PreferSortDescending );
- ImGui::TableSetupColumn( "Appeared at", ImGuiTableColumnFlags_DefaultSort );
- ImGui::TableSetupColumn( "Duration", ImGuiTableColumnFlags_PreferSortDescending );
- ImGui::TableSetupColumn( "Thread", ImGuiTableColumnFlags_NoSort );
- ImGui::TableSetupColumn( "Zone alloc", ImGuiTableColumnFlags_NoSort );
- ImGui::TableSetupColumn( "Zone free", ImGuiTableColumnFlags_NoSort );
- ImGui::TableSetupColumn( "Call stack", ImGuiTableColumnFlags_NoSort );
- ImGui::TableHeadersRow();
-
- const auto& mem = m_worker.GetMemoryNamed( pool );
- const auto& sortspec = *ImGui::TableGetSortSpecs()->Specs;
- switch( sortspec.ColumnIndex )
- {
- case 0:
- if( sortspec.SortDirection == ImGuiSortDirection_Ascending )
- {
- pdqsort_branchless( vec.begin(), vec.end(), []( const auto& l, const auto& r ) { return l->Ptr() < r->Ptr(); } );
- }
- else
- {
- pdqsort_branchless( vec.begin(), vec.end(), []( const auto& l, const auto& r ) { return l->Ptr() > r->Ptr(); } );
- }
- break;
- case 1:
- if( sortspec.SortDirection == ImGuiSortDirection_Ascending )
- {
- pdqsort_branchless( vec.begin(), vec.end(), []( const auto& l, const auto& r ) { return l->Size() < r->Size(); } );
- }
- else
- {
- pdqsort_branchless( vec.begin(), vec.end(), []( const auto& l, const auto& r ) { return l->Size() > r->Size(); } );
- }
- break;
- case 2:
- if( sortspec.SortDirection == ImGuiSortDirection_Descending )
- {
- std::reverse( vec.begin(), vec.end() );
- }
- break;
- case 3:
- if( sortspec.SortDirection == ImGuiSortDirection_Ascending )
- {
- pdqsort_branchless( vec.begin(), vec.end(), []( const auto& l, const auto& r ) { return ( l->TimeFree() - l->TimeAlloc() ) < ( r->TimeFree() - r->TimeAlloc() ); } );
- }
- else
- {
- pdqsort_branchless( vec.begin(), vec.end(), []( const auto& l, const auto& r ) { return ( l->TimeFree() - l->TimeAlloc() ) > ( r->TimeFree() - r->TimeAlloc() ); } );
- }
- break;
- default:
- assert( false );
- break;
- }
-
- int idx = 0;
- ImGuiListClipper clipper;
- clipper.Begin( vec.end() - vec.begin() );
- while( clipper.Step() )
- {
- for( auto i=clipper.DisplayStart; i<clipper.DisplayEnd; i++ )
- {
- ImGui::TableNextRow();
- ImGui::TableNextColumn();
-
- auto v = vec[i];
- const auto arrIdx = std::distance( mem.data.begin(), v );
-
- if( m_memoryAllocInfoPool == pool && m_memoryAllocInfoWindow == arrIdx )
- {
- ImGui::PushStyleColor( ImGuiCol_Text, ImVec4( 1.f, 0.f, 0.f, 1.f ) );
- DrawAddress( v );
- ImGui::PopStyleColor();
- }
- else
- {
- DrawAddress( v );
- if( ImGui::IsItemClicked() )
- {
- m_memoryAllocInfoWindow = arrIdx;
- m_memoryAllocInfoPool = pool;
- }
- }
- if( ImGui::IsItemClicked( 2 ) )
- {
- ZoomToRange( v->TimeAlloc(), v->TimeFree() >= 0 ? v->TimeFree() : m_worker.GetLastTime() );
- }
- if( ImGui::IsItemHovered() )
- {
- m_memoryAllocHover = arrIdx;
- m_memoryAllocHoverWait = 2;
- m_memoryAllocHoverPool = pool;
- }
- ImGui::TableNextColumn();
- ImGui::TextUnformatted( MemSizeToString( v->Size() ) );
- ImGui::TableNextColumn();
- ImGui::PushID( idx++ );
- if( ImGui::Selectable( TimeToStringExact( v->TimeAlloc() - startTime ) ) )
- {
- CenterAtTime( v->TimeAlloc() );
- }
- ImGui::PopID();
- ImGui::TableNextColumn();
- if( v->TimeFree() < 0 )
- {
- TextColoredUnformatted( ImVec4( 0.6f, 1.f, 0.6f, 1.f ), TimeToString( m_worker.GetLastTime() - v->TimeAlloc() ) );
- ImGui::TableNextColumn();
- const auto tid = m_worker.DecompressThread( v->ThreadAlloc() );
- SmallColorBox( GetThreadColor( tid, 0 ) );
- ImGui::SameLine();
- ImGui::TextUnformatted( m_worker.GetThreadName( tid ) );
- }
- else
- {
- ImGui::PushID( idx++ );
- if( ImGui::Selectable( TimeToString( v->TimeFree() - v->TimeAlloc() ) ) )
- {
- CenterAtTime( v->TimeFree() );
- }
- ImGui::PopID();
- ImGui::TableNextColumn();
- if( v->ThreadAlloc() == v->ThreadFree() )
- {
- const auto tid = m_worker.DecompressThread( v->ThreadAlloc() );
- SmallColorBox( GetThreadColor( tid, 0 ) );
- ImGui::SameLine();
- ImGui::TextUnformatted( m_worker.GetThreadName( tid ) );
- }
- else
- {
- const auto tidAlloc = m_worker.DecompressThread( v->ThreadAlloc() );
- const auto tidFree = m_worker.DecompressThread( v->ThreadFree() );
- SmallColorBox( GetThreadColor( tidAlloc, 0 ) );
- ImGui::SameLine();
- ImGui::TextUnformatted( m_worker.GetThreadName( tidAlloc ) );
- ImGui::SameLine();
- ImGui::TextUnformatted( "/" );
- ImGui::SameLine();
- SmallColorBox( GetThreadColor( tidFree, 0 ) );
- ImGui::SameLine();
- ImGui::TextUnformatted( m_worker.GetThreadName( tidFree ) );
- }
- }
- ImGui::TableNextColumn();
- auto zone = FindZoneAtTime( m_worker.DecompressThread( v->ThreadAlloc() ), v->TimeAlloc() );
- if( !zone )
- {
- ImGui::TextUnformatted( "-" );
- }
- else
- {
- const auto& srcloc = m_worker.GetSourceLocation( zone->SrcLoc() );
- const auto txt = srcloc.name.active ? m_worker.GetString( srcloc.name ) : m_worker.GetString( srcloc.function );
- ImGui::PushID( idx++ );
- auto sel = ImGui::Selectable( txt, m_zoneInfoWindow == zone );
- auto hover = ImGui::IsItemHovered();
- ImGui::PopID();
- if( sel )
- {
- ShowZoneInfo( *zone );
- }
- if( hover )
- {
- m_zoneHighlight = zone;
- if( IsMouseClicked( 2 ) )
- {
- ZoomToZone( *zone );
- }
- ZoneTooltip( *zone );
- }
- }
- ImGui::TableNextColumn();
- if( v->TimeFree() < 0 )
- {
- TextColoredUnformatted( ImVec4( 0.6f, 1.f, 0.6f, 1.f ), "active" );
- }
- else
- {
- auto zoneFree = FindZoneAtTime( m_worker.DecompressThread( v->ThreadFree() ), v->TimeFree() );
- if( !zoneFree )
- {
- ImGui::TextUnformatted( "-" );
- }
- else
- {
- const auto& srcloc = m_worker.GetSourceLocation( zoneFree->SrcLoc() );
- const auto txt = srcloc.name.active ? m_worker.GetString( srcloc.name ) : m_worker.GetString( srcloc.function );
- ImGui::PushID( idx++ );
- bool sel;
- if( zoneFree == zone )
- {
- ImGui::PushStyleColor( ImGuiCol_Text, ImVec4( 1.f, 1.f, 0.6f, 1.f ) );
- sel = ImGui::Selectable( txt, m_zoneInfoWindow == zoneFree );
- ImGui::PopStyleColor( 1 );
- }
- else
- {
- sel = ImGui::Selectable( txt, m_zoneInfoWindow == zoneFree );
- }
- auto hover = ImGui::IsItemHovered();
- ImGui::PopID();
- if( sel )
- {
- ShowZoneInfo( *zoneFree );
- }
- if( hover )
- {
- m_zoneHighlight = zoneFree;
- if( IsMouseClicked( 2 ) )
- {
- ZoomToZone( *zoneFree );
- }
- ZoneTooltip( *zoneFree );
- }
- }
- }
- ImGui::TableNextColumn();
- if( v->CsAlloc() == 0 )
- {
- TextDisabledUnformatted( "[alloc]" );
- }
- else
- {
- SmallCallstackButton( "alloc", v->CsAlloc(), idx );
- }
- ImGui::SameLine();
- ImGui::Spacing();
- ImGui::SameLine();
- if( v->csFree.Val() == 0 )
- {
- TextDisabledUnformatted( "[free]" );
- }
- else
- {
- SmallCallstackButton( "free", v->csFree.Val(), idx );
- }
- }
- }
- ImGui::EndTable();
- }
-}
-
template<class T>
static tracy_force_inline T* GetFrameTreeItemNoGroup( unordered_flat_map<uint64_t, T>& tree, CallstackFrameId idx, const Worker& worker )
{
@@ -8107,507 +7717,6 @@ unordered_flat_map<uint64_t, CallstackFrameTree> View::GetParentsCallstackFrameT
return root;
}
-
-enum { ChunkBits = 10 };
-enum { PageBits = 10 };
-enum { PageSize = 1 << PageBits };
-enum { PageChunkBits = ChunkBits + PageBits };
-enum { PageChunkSize = 1 << PageChunkBits };
-
-uint32_t MemDecayColor[256] = {
- 0x0, 0xFF077F07, 0xFF078007, 0xFF078207, 0xFF078307, 0xFF078507, 0xFF078707, 0xFF078807,
- 0xFF078A07, 0xFF078B07, 0xFF078D07, 0xFF078F07, 0xFF079007, 0xFF089208, 0xFF089308, 0xFF089508,
- 0xFF089708, 0xFF089808, 0xFF089A08, 0xFF089B08, 0xFF089D08, 0xFF089F08, 0xFF08A008, 0xFF08A208,
- 0xFF09A309, 0xFF09A509, 0xFF09A709, 0xFF09A809, 0xFF09AA09, 0xFF09AB09, 0xFF09AD09, 0xFF09AF09,
- 0xFF09B009, 0xFF09B209, 0xFF09B309, 0xFF09B509, 0xFF0AB70A, 0xFF0AB80A, 0xFF0ABA0A, 0xFF0ABB0A,
- 0xFF0ABD0A, 0xFF0ABF0A, 0xFF0AC00A, 0xFF0AC20A, 0xFF0AC30A, 0xFF0AC50A, 0xFF0AC70A, 0xFF0BC80B,
- 0xFF0BCA0B, 0xFF0BCB0B, 0xFF0BCD0B, 0xFF0BCF0B, 0xFF0BD00B, 0xFF0BD20B, 0xFF0BD30B, 0xFF0BD50B,
- 0xFF0BD70B, 0xFF0BD80B, 0xFF0BDA0B, 0xFF0CDB0C, 0xFF0CDD0C, 0xFF0CDF0C, 0xFF0CE00C, 0xFF0CE20C,
- 0xFF0CE30C, 0xFF0CE50C, 0xFF0CE70C, 0xFF0CE80C, 0xFF0CEA0C, 0xFF0CEB0C, 0xFF0DED0D, 0xFF0DEF0D,
- 0xFF0DF00D, 0xFF0DF20D, 0xFF0DF30D, 0xFF0DF50D, 0xFF0DF70D, 0xFF0DF80D, 0xFF0DFA0D, 0xFF0DFB0D,
- 0xFF0DFD0D, 0xFF0EFF0E, 0xFF0EFF0E, 0xFF0EFF0E, 0xFF0EFF0E, 0xFF0EFF0E, 0xFF0EFF0E, 0xFF0EFF0E,
- 0xFF0EFF0E, 0xFF0EFF0E, 0xFF0EFF0E, 0xFF0EFF0E, 0xFF0EFF0E, 0xFF0FFF0F, 0xFF0FFF0F, 0xFF0FFF0F,
- 0xFF0FFF0F, 0xFF0FFF0F, 0xFF0FFF0F, 0xFF0FFF0F, 0xFF0FFF0F, 0xFF0FFF0F, 0xFF0FFF0F, 0xFF0FFF0F,
- 0xFF10FF10, 0xFF10FF10, 0xFF10FF10, 0xFF10FF10, 0xFF10FF10, 0xFF10FF10, 0xFF10FF10, 0xFF10FF10,
- 0xFF10FF10, 0xFF10FF10, 0xFF10FF10, 0xFF10FF10, 0xFF11FF11, 0xFF11FF11, 0xFF11FF11, 0xFF11FF11,
- 0xFF11FF11, 0xFF11FF11, 0xFF11FF11, 0xFF11FF11, 0xFF11FF11, 0xFF11FF11, 0xFF11FF11, 0xFF12FF12,
- 0x0, 0xFF1212FF, 0xFF1111FF, 0xFF1111FF, 0xFF1111FF, 0xFF1111FF, 0xFF1111FF, 0xFF1111FF,
- 0xFF1111FF, 0xFF1111FF, 0xFF1111FF, 0xFF1111FF, 0xFF1111FF, 0xFF1010FF, 0xFF1010FF, 0xFF1010FF,
- 0xFF1010FF, 0xFF1010FF, 0xFF1010FF, 0xFF1010FF, 0xFF1010FF, 0xFF1010FF, 0xFF1010FF, 0xFF1010FF,
- 0xFF1010FF, 0xFF0F0FFF, 0xFF0F0FFF, 0xFF0F0FFF, 0xFF0F0FFF, 0xFF0F0FFF, 0xFF0F0FFF, 0xFF0F0FFF,
- 0xFF0F0FFF, 0xFF0F0FFF, 0xFF0F0FFF, 0xFF0F0FFF, 0xFF0E0EFF, 0xFF0E0EFF, 0xFF0E0EFF, 0xFF0E0EFF,
- 0xFF0E0EFF, 0xFF0E0EFF, 0xFF0E0EFF, 0xFF0E0EFF, 0xFF0E0EFF, 0xFF0E0EFF, 0xFF0E0EFF, 0xFF0E0EFF,
- 0xFF0D0DFD, 0xFF0D0DFB, 0xFF0D0DFA, 0xFF0D0DF8, 0xFF0D0DF7, 0xFF0D0DF5, 0xFF0D0DF3, 0xFF0D0DF2,
- 0xFF0D0DF0, 0xFF0D0DEF, 0xFF0D0DED, 0xFF0C0CEB, 0xFF0C0CEA, 0xFF0C0CE8, 0xFF0C0CE7, 0xFF0C0CE5,
- 0xFF0C0CE3, 0xFF0C0CE2, 0xFF0C0CE0, 0xFF0C0CDF, 0xFF0C0CDD, 0xFF0C0CDB, 0xFF0B0BDA, 0xFF0B0BD8,
- 0xFF0B0BD7, 0xFF0B0BD5, 0xFF0B0BD3, 0xFF0B0BD2, 0xFF0B0BD0, 0xFF0B0BCF, 0xFF0B0BCD, 0xFF0B0BCB,
- 0xFF0B0BCA, 0xFF0B0BC8, 0xFF0A0AC7, 0xFF0A0AC5, 0xFF0A0AC3, 0xFF0A0AC2, 0xFF0A0AC0, 0xFF0A0ABF,
- 0xFF0A0ABD, 0xFF0A0ABB, 0xFF0A0ABA, 0xFF0A0AB8, 0xFF0A0AB7, 0xFF0909B5, 0xFF0909B3, 0xFF0909B2,
- 0xFF0909B0, 0xFF0909AF, 0xFF0909AD, 0xFF0909AB, 0xFF0909AA, 0xFF0909A8, 0xFF0909A7, 0xFF0909A5,
- 0xFF0909A3, 0xFF0808A2, 0xFF0808A0, 0xFF08089F, 0xFF08089D, 0xFF08089B, 0xFF08089A, 0xFF080898,
- 0xFF080897, 0xFF080895, 0xFF080893, 0xFF080892, 0xFF070790, 0xFF07078F, 0xFF07078D, 0xFF07078B,
- 0xFF07078A, 0xFF070788, 0xFF070787, 0xFF070785, 0xFF070783, 0xFF070782, 0xFF070780, 0xFF07077F,
-};
-
-struct MemoryPage
-{
- uint64_t page;
- int8_t data[PageSize];
-};
-
-static tracy_force_inline MemoryPage& GetPage( unordered_flat_map<uint64_t, MemoryPage>& memmap, uint64_t page )
-{
- auto it = memmap.find( page );
- if( it == memmap.end() )
- {
- it = memmap.emplace( page, MemoryPage { page, {} } ).first;
- }
- return it->second;
-}
-
-static tracy_force_inline void FillPages( unordered_flat_map<uint64_t, MemoryPage>& memmap, uint64_t c0, uint64_t c1, int8_t val )
-{
- auto p0 = c0 >> PageBits;
- const auto p1 = c1 >> PageBits;
-
- if( p0 == p1 )
- {
- const auto a0 = c0 & ( PageSize - 1 );
- const auto a1 = c1 & ( PageSize - 1 );
-
- auto& page = GetPage( memmap, p0 );
- if( a0 == a1 )
- {
- page.data[a0] = val;
- }
- else
- {
- memset( page.data + a0, val, a1 - a0 + 1 );
- }
- }
- else
- {
- {
- const auto a0 = c0 & ( PageSize - 1 );
- auto& page = GetPage( memmap, p0 );
- memset( page.data + a0, val, PageSize - a0 );
- }
- while( ++p0 < p1 )
- {
- auto& page = GetPage( memmap, p0 );
- memset( page.data, val, PageSize );
- }
- {
- const auto a1 = c1 & ( PageSize - 1 );
- auto& page = GetPage( memmap, p1 );
- memset( page.data, val, a1 + 1 );
- }
- }
-}
-
-std::vector<MemoryPage> View::GetMemoryPages() const
-{
- std::vector<MemoryPage> ret;
-
- static unordered_flat_map<uint64_t, MemoryPage> memmap;
-
- const auto& mem = m_worker.GetMemoryNamed( m_memInfo.pool );
- const auto memlow = mem.low;
-
- if( m_memInfo.range.active )
- {
- auto it = std::lower_bound( mem.data.begin(), mem.data.end(), m_memInfo.range.min, []( const auto& lhs, const auto& rhs ) { return lhs.TimeAlloc() < rhs; } );
- if( it != mem.data.end() )
- {
- auto end = std::lower_bound( mem.data.begin(), mem.data.end(), m_memInfo.range.max, []( const auto& lhs, const auto& rhs ) { return lhs.TimeAlloc() < rhs; } );
- while( it != end )
- {
- auto& alloc = *it++;
-
- const auto a0 = alloc.Ptr() - memlow;
- const auto a1 = a0 + alloc.Size();
- int8_t val = alloc.TimeFree() < 0 ?
- int8_t( std::max( int64_t( 1 ), 127 - ( ( m_memInfo.range.max - alloc.TimeAlloc() ) >> 24 ) ) ) :
- ( alloc.TimeFree() > m_memInfo.range.max ?
- int8_t( std::max( int64_t( 1 ), 127 - ( ( m_memInfo.range.max - alloc.TimeAlloc() ) >> 24 ) ) ) :
- int8_t( -std::max( int64_t( 1 ), 127 - ( ( m_memInfo.range.max - alloc.TimeFree() ) >> 24 ) ) ) );
-
- const auto c0 = a0 >> ChunkBits;
- const auto c1 = a1 >> ChunkBits;
-
- FillPages( memmap, c0, c1, val );
- }
- }
- }
- else
- {
- const auto lastTime = m_worker.GetLastTime();
- for( auto& alloc : mem.data )
- {
- const auto a0 = alloc.Ptr() - memlow;
- const auto a1 = a0 + alloc.Size();
- const int8_t val = alloc.TimeFree() < 0 ?
- int8_t( std::max( int64_t( 1 ), 127 - ( ( lastTime - std::min( lastTime, alloc.TimeAlloc() ) ) >> 24 ) ) ) :
- int8_t( -std::max( int64_t( 1 ), 127 - ( ( lastTime - std::min( lastTime, alloc.TimeFree() ) ) >> 24 ) ) );
-
- const auto c0 = a0 >> ChunkBits;
- const auto c1 = a1 >> ChunkBits;
-
- FillPages( memmap, c0, c1, val );
- }
- }
-
- std::vector<unordered_flat_map<uint64_t, MemoryPage>::const_iterator> itmap;
- itmap.reserve( memmap.size() );
- ret.reserve( memmap.size() );
- for( auto it = memmap.begin(); it != memmap.end(); ++it ) itmap.emplace_back( it );
- pdqsort_branchless( itmap.begin(), itmap.end(), []( const auto& lhs, const auto& rhs ) { return lhs->second.page < rhs->second.page; } );
- for( auto& v : itmap ) ret.emplace_back( v->second );
-
- memmap.clear();
- return ret;
-}
-
-void View::DrawMemory()
-{
- const auto scale = GetScale();
- ImGui::SetNextWindowSize( ImVec2( 1100 * scale, 500 * scale ), ImGuiCond_FirstUseEver );
- ImGui::Begin( "Memory", &m_memInfo.show, ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse );
- if( ImGui::GetCurrentWindowRead()->SkipItems ) { ImGui::End(); return; }
-
- auto& memNameMap = m_worker.GetMemNameMap();
- if( memNameMap.size() > 1 )
- {
- TextDisabledUnformatted( ICON_FA_ARCHIVE " Memory pool:" );
- ImGui::SameLine();
- if( ImGui::BeginCombo( "##memoryPool", m_memInfo.pool == 0 ? "Default allocator" : m_worker.GetString( m_memInfo.pool ) ) )
- {
- for( auto& v : memNameMap )
- {
- if( ImGui::Selectable( v.first == 0 ? "Default allocator" : m_worker.GetString( v.first ) ) )
- {
- m_memInfo.pool = v.first;
- m_memInfo.showAllocList = false;
- }
- }
- ImGui::EndCombo();
- }
- ImGui::Separator();
- }
-
- auto& mem = m_worker.GetMemoryNamed( m_memInfo.pool );
- if( mem.data.empty() )
- {
- ImGui::TextWrapped( "No memory data collected." );
- ImGui::End();
- return;
- }
-
- TextDisabledUnformatted( "Total allocations:" );
- ImGui::SameLine();
- ImGui::Text( "%-15s", RealToString( mem.data.size() ) );
- ImGui::SameLine();
- TextDisabledUnformatted( "Active allocations:" );
- ImGui::SameLine();
- ImGui::Text( "%-15s", RealToString( mem.active.size() ) );
- ImGui::SameLine();
- TextDisabledUnformatted( "Memory usage:" );
- ImGui::SameLine();
- ImGui::Text( "%-15s", MemSizeToString( mem.usage ) );
- ImGui::SameLine();
- TextFocused( "Memory span:", MemSizeToString( mem.high - mem.low ) );
- ImGui::SameLine();
- ImGui::Spacing();
- ImGui::SameLine();
- DrawHelpMarker(
- "Click on address to display memory allocation info window. Middle click to zoom to allocation range.\n"
- "Active allocations are displayed using green color.\n"
- "A single thread is displayed if alloc and free was performed on the same thread. Otherwise two threads are displayed in order: alloc, free.\n"
- "If alloc and free is performed in the same zone, the free zone is displayed in yellow color." );
- ImGui::SameLine();
- ImGui::Spacing();
- ImGui::SameLine();
- ImGui::SeparatorEx( ImGuiSeparatorFlags_Vertical );
- ImGui::SameLine();
- ImGui::Spacing();
- ImGui::SameLine();
- ImGui::PushStyleVar( ImGuiStyleVar_FramePadding, ImVec2( 2, 2 ) );
- if( ImGui::Checkbox( "Limit range", &m_memInfo.range.active ) )
- {
- if( m_memInfo.range.active && m_memInfo.range.min == 0 && m_memInfo.range.max == 0 )
- {
- m_memInfo.range.min = m_vd.zvStart;
- m_memInfo.range.max = m_vd.zvEnd;
- }
- }
- if( m_memInfo.range.active )
- {
- ImGui::SameLine();
- TextColoredUnformatted( 0xFF00FFFF, ICON_FA_EXCLAMATION_TRIANGLE );
- ImGui::SameLine();
- ToggleButton( ICON_FA_RULER " Limits", m_showRanges );
- }
- ImGui::PopStyleVar();
-
- ImGui::Separator();
- ImGui::BeginChild( "##memory" );
- if( ImGui::TreeNode( ICON_FA_AT " Allocations" ) )
- {
- bool findClicked = ImGui::InputTextWithHint( "###address", "Enter memory address to search for", m_memInfo.pattern, 1024, ImGuiInputTextFlags_EnterReturnsTrue );
- ImGui::SameLine();
- findClicked |= ImGui::Button( ICON_FA_SEARCH " Find" );
- if( findClicked )
- {
- m_memInfo.ptrFind = strtoull( m_memInfo.pattern, nullptr, 0 );
- }
- ImGui::SameLine();
- if( ImGui::Button( ICON_FA_BACKSPACE " Clear" ) )
- {
- m_memInfo.ptrFind = 0;
- m_memInfo.pattern[0] = '\0';
- }
-
- if( m_memInfo.ptrFind != 0 )
- {
- std::vector<const MemEvent*> match;
- match.reserve( mem.active.size() ); // heuristic
- if( m_memInfo.range.active )
- {
- auto it = std::lower_bound( mem.data.begin(), mem.data.end(), m_memInfo.range.min, [] ( const auto& lhs, const auto& rhs ) { return lhs.TimeAlloc() < rhs; } );
- if( it != mem.data.end() )
- {
- auto end = std::lower_bound( it, mem.data.end(), m_memInfo.range.max, [] ( const auto& lhs, const auto& rhs ) { return lhs.TimeAlloc() < rhs; } );
- while( it != end )
- {
- if( it->Ptr() <= m_memInfo.ptrFind && it->Ptr() + it->Size() > m_memInfo.ptrFind )
- {
- match.emplace_back( it );
- }
- ++it;
- }
- }
- }
- else
- {
- for( auto& v : mem.data )
- {
- if( v.Ptr() <= m_memInfo.ptrFind && v.Ptr() + v.Size() > m_memInfo.ptrFind )
- {
- match.emplace_back( &v );
- }
- }
- }
-
- if( match.empty() )
- {
- ImGui::TextUnformatted( "Found no allocations at given address" );
- }
- else
- {
- ListMemData( match, [this]( auto v ) {
- if( v->Ptr() == m_memInfo.ptrFind )
- {
- ImGui::Text( "0x%" PRIx64, m_memInfo.ptrFind );
- }
- else
- {
- ImGui::Text( "0x%" PRIx64 "+%" PRIu64, v->Ptr(), m_memInfo.ptrFind - v->Ptr() );
- }
- }, "##allocations", -1, m_memInfo.pool );
- }
- }
- ImGui::TreePop();
- }
-
- ImGui::Separator();
- if( ImGui::TreeNode( ICON_FA_HEARTBEAT " Active allocations" ) )
- {
- uint64_t total = 0;
- std::vector<const MemEvent*> items;
- items.reserve( mem.active.size() );
- if( m_memInfo.range.active )
- {
- auto it = std::lower_bound( mem.data.begin(), mem.data.end(), m_memInfo.range.min, [] ( const auto& lhs, const auto& rhs ) { return lhs.TimeAlloc() < rhs; } );
- if( it != mem.data.end() )
- {
- auto end = std::lower_bound( it, mem.data.end(), m_memInfo.range.max, [] ( const auto& lhs, const auto& rhs ) { return lhs.TimeAlloc() < rhs; } );
- while( it != end )
- {
- const auto tf = it->TimeFree();
- if( tf < 0 || tf >= m_memInfo.range.max )
- {
- items.emplace_back( it );
- total += it->Size();
- }
- ++it;
- }
- }
- }
- else
- {
- auto ptr = mem.data.data();
- for( auto& v : mem.active ) items.emplace_back( ptr + v.second );
- pdqsort_branchless( items.begin(), items.end(), []( const auto& lhs, const auto& rhs ) { return lhs->TimeAlloc() < rhs->TimeAlloc(); } );
- total = mem.usage;
- }
-
- ImGui::SameLine();
- ImGui::TextDisabled( "(%s)", RealToString( items.size() ) );
- ImGui::SameLine();
- ImGui::Spacing();
- ImGui::SameLine();
- TextFocused( "Memory usage:", MemSizeToString( total ) );
-
- if( !items.empty() )
- {
- ListMemData( items, []( auto v ) {
- ImGui::Text( "0x%" PRIx64, v->Ptr() );
- }, "##activeMem", -1, m_memInfo.pool );
- }
- else
- {
- TextDisabledUnformatted( "No active allocations" );
- }
- ImGui::TreePop();
- }
-
- ImGui::Separator();
- if( ImGui::TreeNode( ICON_FA_MAP " Memory map" ) )
- {
- ImGui::SameLine();
- ImGui::Spacing();
- ImGui::SameLine();
- TextFocused( "Single pixel:", MemSizeToString( 1 << ChunkBits ) );
- ImGui::SameLine();
- ImGui::Spacing();
- ImGui::SameLine();
- TextFocused( "Single line:", MemSizeToString( PageChunkSize ) );
-
- auto pages = GetMemoryPages();
- const size_t lines = pages.size();
-
- ImGui::BeginChild( "##memMap", ImVec2( PageSize + 2, lines + 2 ), false );
- auto draw = ImGui::GetWindowDrawList();
- const auto wpos = ImGui::GetCursorScreenPos() + ImVec2( 1, 1 );
- const auto dpos = wpos + ImVec2( 0.5f, 0.5f );
- draw->AddRect( wpos - ImVec2( 1, 1 ), wpos + ImVec2( PageSize + 1, lines + 1 ), 0xFF666666 );
- draw->AddRectFilled( wpos, wpos + ImVec2( PageSize, lines ), 0xFF444444 );
-
- size_t line = 0;
- for( auto& page : pages )
- {
- size_t idx = 0;
- while( idx < PageSize )
- {
- if( page.data[idx] == 0 )
- {
- do
- {
- idx++;
- }
- while( idx < PageSize && page.data[idx] == 0 );
- }
- else
- {
- auto val = page.data[idx];
- const auto i0 = idx;
- do
- {
- idx++;
- }
- while( idx < PageSize && page.data[idx] == val );
- DrawLine( draw, dpos + ImVec2( i0, line ), dpos + ImVec2( idx, line ), MemDecayColor[(uint8_t)val] );
- }
- }
- line++;
- }
-
- ImGui::EndChild();
- ImGui::TreePop();
- }
-
- ImGui::PushID( m_memInfo.pool );
- ImGui::Separator();
- if( ImGui::TreeNode( ICON_FA_TREE " Bottom-up call stack tree" ) )
- {
- ImGui::SameLine();
- DrawHelpMarker( "Press ctrl key to display allocation info tooltip. Right click on function name to display allocations list." );
- ImGui::SameLine();
- ImGui::Spacing();
- ImGui::SameLine();
- SmallCheckbox( "Group by function name", &m_groupCallstackTreeByNameBottomUp );
- ImGui::SameLine();
- DrawHelpMarker( "If enabled, only one source location will be displayed (which may be incorrect)." );
- ImGui::SameLine();
- ImGui::Spacing();
- ImGui::SameLine();
- bool activeOnlyBottomUp = m_memRangeBottomUp == MemRange::Active;
- if( SmallCheckbox( "Only active allocations", &activeOnlyBottomUp ) )
- m_memRangeBottomUp = activeOnlyBottomUp ? MemRange::Active : MemRange::Full;
- ImGui::SameLine();
- ImGui::Spacing();
- ImGui::SameLine();
- bool inactiveOnlyBottomUp = m_memRangeBottomUp == MemRange::Inactive;
- if( SmallCheckbox( "Only inactive allocations", &inactiveOnlyBottomUp ) )
- m_memRangeBottomUp = inactiveOnlyBottomUp ? MemRange::Inactive : MemRange::Full;
-
- auto tree = GetCallstackFrameTreeBottomUp( mem );
- if( !tree.empty() )
- {
- int idx = 0;
- DrawFrameTreeLevel( tree, idx );
- }
- else
- {
- TextDisabledUnformatted( "No call stack data collected" );
- }
-
- ImGui::TreePop();
- }
-
- ImGui::Separator();
- if( ImGui::TreeNode( ICON_FA_TREE " Top-down call stack tree" ) )
- {
- ImGui::SameLine();
- DrawHelpMarker( "Press ctrl key to display allocation info tooltip. Right click on function name to display allocations list." );
- ImGui::SameLine();
- ImGui::Spacing();
- ImGui::SameLine();
- SmallCheckbox( "Group by function name", &m_groupCallstackTreeByNameTopDown );
- ImGui::SameLine();
- DrawHelpMarker( "If enabled, only one source location will be displayed (which may be incorrect)." );
- ImGui::SameLine();
- ImGui::Spacing();
- ImGui::SameLine();
- bool activeOnlyTopDown = m_memRangeTopDown == MemRange::Active;
- if( SmallCheckbox( "Only active allocations", &activeOnlyTopDown ) )
- m_memRangeTopDown = activeOnlyTopDown ? MemRange::Active : MemRange::Full;
- ImGui::SameLine();
- ImGui::Spacing();
- ImGui::SameLine();
- bool inactiveOnlyTopDown = m_memRangeTopDown == MemRange::Inactive;
- if( SmallCheckbox( "Only inactive allocations", &inactiveOnlyTopDown ) )
- m_memRangeTopDown = inactiveOnlyTopDown ? MemRange::Inactive : MemRange::Full;
-
- auto tree = GetCallstackFrameTreeTopDown( mem );
- if( !tree.empty() )
- {
- int idx = 0;
- DrawFrameTreeLevel( tree, idx );
- }
- else
- {
- TextDisabledUnformatted( "No call stack data collected" );
- }
-
- ImGui::TreePop();
- }
- ImGui::PopID();
-
- ImGui::EndChild();
- ImGui::End();
-}
-
void View::DrawFrameTreeLevel( const unordered_flat_map<uint64_t, MemCallstackFrameTree>& tree, int& idx )
{
auto& io = ImGui::GetIO();