com.alicizax.unity.framework/Editor/Inspector/MemoryPoolComponentInspector.cs

171 lines
7.9 KiB
C#
Raw Normal View History

2026-04-21 14:24:36 +08:00
using AlicizaX;
2025-10-11 15:18:09 +08:00
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using UnityEditor;
using UnityEngine;
namespace AlicizaX.Editor
{
[CustomEditor(typeof(MemoryPoolSetting))]
internal sealed class MemoryPoolComponentInspector : GameFrameworkInspector
{
private readonly Dictionary<string, List<MemoryPoolInfo>> m_ReferencePoolInfos = new Dictionary<string, List<MemoryPoolInfo>>(StringComparer.Ordinal);
private readonly HashSet<string> m_OpenedItems = new HashSet<string>();
private SerializedProperty m_EnableStrictCheck = null;
private bool m_ShowFullClassName = false;
public override void OnInspectorGUI()
{
base.OnInspectorGUI();
serializedObject.Update();
MemoryPoolSetting t = (MemoryPoolSetting)target;
if (EditorApplication.isPlaying && IsPrefabInHierarchy(t.gameObject))
{
bool enableStrictCheck = EditorGUILayout.Toggle("Enable Strict Check", t.EnableStrictCheck);
if (enableStrictCheck != t.EnableStrictCheck)
{
t.EnableStrictCheck = enableStrictCheck;
}
2026-04-21 14:24:36 +08:00
EditorGUILayout.LabelField("Memory Pool Count", MemoryPool.Count.ToString());
2025-10-11 15:18:09 +08:00
m_ShowFullClassName = EditorGUILayout.Toggle("Show Full Class Name", m_ShowFullClassName);
2026-04-21 14:24:36 +08:00
// 全局统计
2025-10-11 15:18:09 +08:00
MemoryPoolInfo[] referencePoolInfos = MemoryPool.GetAllMemoryPoolInfos();
2026-04-21 14:24:36 +08:00
int totalUnused = 0, totalUsing = 0, totalArrayLen = 0;
foreach (var info in referencePoolInfos)
{
totalUnused += info.UnusedCount;
totalUsing += info.UsingCount;
totalArrayLen += info.PoolArrayLength;
}
EditorGUILayout.LabelField("Total Cached", totalUnused.ToString());
EditorGUILayout.LabelField("Total In Use", totalUsing.ToString());
EditorGUILayout.LabelField("Total Array Capacity", totalArrayLen.ToString());
EditorGUILayout.Space();
// 全局操作按钮
EditorGUILayout.BeginHorizontal();
if (GUILayout.Button("Clear All Pools"))
{
MemoryPoolRegistry.ClearAll();
}
EditorGUILayout.EndHorizontal();
EditorGUILayout.Space();
// 按 Assembly 分组
m_ReferencePoolInfos.Clear();
2025-10-11 15:18:09 +08:00
foreach (MemoryPoolInfo referencePoolInfo in referencePoolInfos)
{
string assemblyName = referencePoolInfo.Type.Assembly.GetName().Name;
2026-04-21 14:24:36 +08:00
if (!m_ReferencePoolInfos.TryGetValue(assemblyName, out List<MemoryPoolInfo> results))
2025-10-11 15:18:09 +08:00
{
results = new List<MemoryPoolInfo>();
m_ReferencePoolInfos.Add(assemblyName, results);
}
results.Add(referencePoolInfo);
}
foreach (KeyValuePair<string, List<MemoryPoolInfo>> assemblyReferencePoolInfo in m_ReferencePoolInfos)
{
bool lastState = m_OpenedItems.Contains(assemblyReferencePoolInfo.Key);
bool currentState = EditorGUILayout.Foldout(lastState, assemblyReferencePoolInfo.Key);
if (currentState != lastState)
{
if (currentState)
m_OpenedItems.Add(assemblyReferencePoolInfo.Key);
else
m_OpenedItems.Remove(assemblyReferencePoolInfo.Key);
}
if (currentState)
{
EditorGUILayout.BeginVertical("box");
{
2026-04-21 14:24:36 +08:00
var label = "Unused\tUsing\tAcquire\tRelease\tCreated\tHiWater\tMaxCap\tIdle\tArrLen";
2025-10-11 15:18:09 +08:00
EditorGUILayout.LabelField(m_ShowFullClassName ? "Full Class Name" : "Class Name", label);
assemblyReferencePoolInfo.Value.Sort(Comparison);
foreach (MemoryPoolInfo referencePoolInfo in assemblyReferencePoolInfo.Value)
{
DrawReferencePoolInfo(referencePoolInfo);
}
if (GUILayout.Button("Export CSV Data"))
{
2026-04-21 14:24:36 +08:00
string exportFileName = EditorUtility.SaveFilePanel("Export CSV Data", string.Empty, Utility.Text.Format("Memory Pool Data - {0}.csv", assemblyReferencePoolInfo.Key), string.Empty);
2025-10-11 15:18:09 +08:00
if (!string.IsNullOrEmpty(exportFileName))
{
try
{
int index = 0;
string[] data = new string[assemblyReferencePoolInfo.Value.Count + 1];
2026-04-21 14:24:36 +08:00
data[index++] = "Class Name,Full Class Name,Unused,Using,Acquire,Release,Created,HighWaterMark,MaxCapacity,IdleFrames,ArrayLength";
foreach (MemoryPoolInfo info in assemblyReferencePoolInfo.Value)
2025-10-11 15:18:09 +08:00
{
2026-04-21 14:24:36 +08:00
data[index++] = Utility.Text.Format("{0},{1},{2},{3},{4},{5},{6},{7},{8},{9},{10}",
info.Type.Name, info.Type.FullName,
info.UnusedCount, info.UsingCount,
info.AcquireCount, info.ReleaseCount,
info.CreateCount, info.HighWaterMark,
info.MaxCapacity, info.IdleFrames, info.PoolArrayLength);
2025-10-11 15:18:09 +08:00
}
File.WriteAllLines(exportFileName, data, Encoding.UTF8);
2026-04-21 14:24:36 +08:00
Debug.Log(Utility.Text.Format("Export memory pool CSV data to '{0}' success.", exportFileName));
2025-10-11 15:18:09 +08:00
}
catch (Exception exception)
{
2026-04-21 14:24:36 +08:00
Debug.LogError(Utility.Text.Format("Export memory pool CSV data to '{0}' failure, exception is '{1}'.", exportFileName, exception));
2025-10-11 15:18:09 +08:00
}
}
}
}
EditorGUILayout.EndVertical();
EditorGUILayout.Separator();
}
}
}
else
{
EditorGUILayout.PropertyField(m_EnableStrictCheck);
}
serializedObject.ApplyModifiedProperties();
Repaint();
}
private void OnEnable()
{
m_EnableStrictCheck = serializedObject.FindProperty("m_EnableStrictCheck");
}
2026-04-21 14:24:36 +08:00
private void DrawReferencePoolInfo(MemoryPoolInfo info)
2025-10-11 15:18:09 +08:00
{
2026-04-21 14:24:36 +08:00
string name = m_ShowFullClassName ? info.Type.FullName : info.Type.Name;
string values = Utility.Text.Format("{0}\t{1}\t{2}\t{3}\t{4}\t{5}\t{6}\t{7}\t{8}",
info.UnusedCount, info.UsingCount,
info.AcquireCount, info.ReleaseCount,
info.CreateCount, info.HighWaterMark,
info.MaxCapacity, info.IdleFrames, info.PoolArrayLength);
EditorGUILayout.LabelField(name, values);
2025-10-11 15:18:09 +08:00
}
private int Comparison(MemoryPoolInfo a, MemoryPoolInfo b)
{
if (m_ShowFullClassName)
return a.Type.FullName.CompareTo(b.Type.FullName);
else
return a.Type.Name.CompareTo(b.Type.Name);
}
}
}