2026-04-21 13:01:55 +08:00
using System ;
2025-09-05 19:46:30 +08:00
using System.Collections.Generic ;
using UnityEngine ;
2026-04-21 13:01:55 +08:00
using UnityEngine.UIElements ;
2025-09-05 19:46:30 +08:00
namespace AlicizaX.Debugger.Runtime
{
public sealed partial class DebuggerComponent
{
2026-04-21 13:01:55 +08:00
private sealed class ReferencePoolInformationWindow : PollingDebuggerWindowBase
2025-09-05 19:46:30 +08:00
{
private readonly Dictionary < string , List < MemoryPoolInfo > > m_ReferencePoolInfos = new Dictionary < string , List < MemoryPoolInfo > > ( StringComparer . Ordinal ) ;
private readonly Comparison < MemoryPoolInfo > m_NormalClassNameComparer = NormalClassNameComparer ;
private readonly Comparison < MemoryPoolInfo > m_FullClassNameComparer = FullClassNameComparer ;
2026-04-21 13:01:55 +08:00
private bool m_ShowFullClassName ;
private Toggle showFullClassNameToggle ;
2025-09-05 19:46:30 +08:00
2026-04-21 13:01:55 +08:00
protected override void BuildWindow ( VisualElement root )
2025-09-05 19:46:30 +08:00
{
2026-04-21 14:24:36 +08:00
float scale = DebuggerComponent . Instance ! = null ? DebuggerComponent . Instance . GetUiScale ( ) : 1f ;
// ---- Overview Section ----
VisualElement overview = CreateSection ( "Memory Pool Overview" , out VisualElement overviewCard ) ;
2026-04-21 13:01:55 +08:00
overviewCard . Add ( CreateRow ( "Enable Strict Check" , MemoryPool . EnableStrictCheck . ToString ( ) ) ) ;
2026-04-21 14:24:36 +08:00
overviewCard . Add ( CreateRow ( "Pool Type Count" , MemoryPool . Count . ToString ( ) ) ) ;
// 统计总缓存对象数和总数组容量
MemoryPoolInfo [ ] allInfos = MemoryPool . GetAllMemoryPoolInfos ( ) ;
int totalUnused = 0 ;
int totalUsing = 0 ;
int totalArrayLen = 0 ;
foreach ( var info in allInfos )
{
totalUnused + = info . UnusedCount ;
totalUsing + = info . UsingCount ;
totalArrayLen + = info . PoolArrayLength ;
}
overviewCard . Add ( CreateRow ( "Total Cached Objects" , totalUnused . ToString ( ) ) ) ;
overviewCard . Add ( CreateRow ( "Total In Use" , totalUsing . ToString ( ) ) ) ;
overviewCard . Add ( CreateRow ( "Total Array Capacity" , totalArrayLen . ToString ( ) ) ) ;
showFullClassNameToggle = CreateConsoleFilterToggle ( "Show Full ClassName" , m_ShowFullClassName , DebuggerTheme . PrimaryText , value = > m_ShowFullClassName = value ) ;
2026-04-21 13:01:55 +08:00
overviewCard . Add ( showFullClassNameToggle ) ;
2026-04-21 14:24:36 +08:00
// ---- 操作按钮 ----
VisualElement buttonRow = new VisualElement ( ) ;
buttonRow . style . flexDirection = FlexDirection . Row ;
buttonRow . style . marginTop = 8f * scale ;
buttonRow . Add ( CreateActionButton ( "Clear All Pools" , ( ) = >
{
MemoryPoolRegistry . ClearAll ( ) ;
Rebuild ( ) ;
} , DebuggerTheme . Danger ) ) ;
overviewCard . Add ( buttonRow ) ;
2026-04-21 13:01:55 +08:00
root . Add ( overview ) ;
2025-09-05 19:46:30 +08:00
2026-04-21 14:24:36 +08:00
// ---- 按 Assembly 分组 ----
2025-09-05 19:46:30 +08:00
m_ReferencePoolInfos . Clear ( ) ;
2026-04-21 14:24:36 +08:00
foreach ( MemoryPoolInfo info in allInfos )
2025-09-05 19:46:30 +08:00
{
2026-04-21 14:24:36 +08:00
string assemblyName = info . Type . Assembly . GetName ( ) . Name ;
2026-04-21 13:01:55 +08:00
if ( ! m_ReferencePoolInfos . TryGetValue ( assemblyName , out List < MemoryPoolInfo > results ) )
2025-09-05 19:46:30 +08:00
{
results = new List < MemoryPoolInfo > ( ) ;
m_ReferencePoolInfos . Add ( assemblyName , results ) ;
}
2026-04-21 14:24:36 +08:00
results . Add ( info ) ;
2025-09-05 19:46:30 +08:00
}
2026-04-21 14:24:36 +08:00
foreach ( KeyValuePair < string , List < MemoryPoolInfo > > assemblyInfo in m_ReferencePoolInfos )
2025-09-05 19:46:30 +08:00
{
2026-04-21 14:24:36 +08:00
assemblyInfo . Value . Sort ( m_ShowFullClassName ? m_FullClassNameComparer : m_NormalClassNameComparer ) ;
VisualElement section = CreateSection ( Utility . Text . Format ( "Assembly: {0}" , assemblyInfo . Key ) , out VisualElement card ) ;
if ( assemblyInfo . Value . Count < = 0 )
2025-09-05 19:46:30 +08:00
{
2026-04-21 14:24:36 +08:00
card . Add ( CreateRow ( "State" , "Memory Pool is Empty ..." ) ) ;
2026-04-21 13:01:55 +08:00
}
else
{
2026-04-21 14:24:36 +08:00
for ( int i = 0 ; i < assemblyInfo . Value . Count ; i + + )
2025-09-05 19:46:30 +08:00
{
2026-04-21 14:24:36 +08:00
card . Add ( CreatePoolInfoItem ( assemblyInfo . Value [ i ] , m_ShowFullClassName , scale ) ) ;
2025-09-05 19:46:30 +08:00
}
}
2026-04-21 13:01:55 +08:00
root . Add ( section ) ;
2025-09-05 19:46:30 +08:00
}
}
private static int NormalClassNameComparer ( MemoryPoolInfo a , MemoryPoolInfo b )
{
return a . Type . Name . CompareTo ( b . Type . Name ) ;
}
private static int FullClassNameComparer ( MemoryPoolInfo a , MemoryPoolInfo b )
{
return a . Type . FullName . CompareTo ( b . Type . FullName ) ;
}
2026-04-21 13:01:55 +08:00
2026-04-21 14:24:36 +08:00
private static VisualElement CreatePoolInfoItem ( MemoryPoolInfo info , bool showFullName , float scale )
2026-04-21 13:01:55 +08:00
{
VisualElement item = CreateCard ( ) ;
item . style . marginBottom = 8f * scale ;
item . style . backgroundColor = DebuggerTheme . PanelSurfaceAlt ;
2026-04-21 14:24:36 +08:00
string title = showFullName ? info . Type . FullName : info . Type . Name ;
2026-04-21 13:01:55 +08:00
Label titleLabel = new Label ( title ? ? string . Empty ) ;
titleLabel . style . color = DebuggerTheme . PrimaryText ;
titleLabel . style . fontSize = 16f * scale ;
titleLabel . style . unityFontStyleAndWeight = FontStyle . Bold ;
titleLabel . style . whiteSpace = WhiteSpace . Normal ;
titleLabel . style . marginBottom = 6f * scale ;
2026-04-21 14:24:36 +08:00
item . Add ( titleLabel ) ;
2026-04-21 13:01:55 +08:00
2026-04-21 14:24:36 +08:00
// 基础统计
string stats = Utility . Text . Format (
"Unused {0} | Using {1} | Acquire {2} | Release {3} | Created {4}" ,
info . UnusedCount , info . UsingCount ,
info . AcquireCount , info . ReleaseCount ,
info . CreateCount ) ;
Label statsLabel = new Label ( stats ) ;
statsLabel . style . color = DebuggerTheme . SecondaryText ;
statsLabel . style . fontSize = 14f * scale ;
statsLabel . style . whiteSpace = WhiteSpace . Normal ;
statsLabel . style . marginBottom = 4f * scale ;
item . Add ( statsLabel ) ;
2026-04-21 13:01:55 +08:00
2026-04-21 14:24:36 +08:00
// 回收策略状态
string recycleStatus = Utility . Text . Format (
"HighWater {0} | MaxCap {1} | Idle {2}f | Array {3}" ,
info . HighWaterMark , info . MaxCapacity ,
info . IdleFrames , info . PoolArrayLength ) ;
Label recycleLabel = new Label ( recycleStatus ) ;
recycleLabel . style . fontSize = 13f * scale ;
recycleLabel . style . whiteSpace = WhiteSpace . Normal ;
// 根据空闲帧数着色:接近回收阈值时变色
if ( info . IdleFrames > = 300 )
recycleLabel . style . color = DebuggerTheme . Warning ;
else if ( info . IdleFrames > = 200 )
recycleLabel . style . color = new Color ( 0.9f , 0.7f , 0.3f ) ;
else
recycleLabel . style . color = DebuggerTheme . SecondaryText ;
item . Add ( recycleLabel ) ;
2026-04-21 13:01:55 +08:00
return item ;
}
2025-09-05 19:46:30 +08:00
}
}
}