Skip to content

Commit 359fcae

Browse files
perf(ui): optimize MessageBox for zero GC allocation
- Replace HashSet with List (no need for hash-based uniqueness) - Use ArrayPool for CloseAll() instead of allocating new array - Remove LINQ dependency (use direct list indexing) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> Signed-off-by: JasonXuDeveloper - 傑 <jason@xgamedev.net>
1 parent aaa05b2 commit 359fcae

1 file changed

Lines changed: 19 additions & 10 deletions

File tree

  • UnityProject/Packages/com.jasonxudeveloper.jengine.ui/Runtime

UnityProject/Packages/com.jasonxudeveloper.jengine.ui/Runtime/MessageBox.cs

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,8 @@
2424
// THE SOFTWARE.
2525

2626
using System;
27+
using System.Buffers;
2728
using System.Collections.Generic;
28-
using System.Linq;
2929
using System.Runtime.CompilerServices;
3030
using Cysharp.Threading.Tasks;
3131
using TMPro;
@@ -106,7 +106,7 @@ private static GameObject Prefab
106106

107107
private static GameObject _prefab;
108108

109-
private static readonly HashSet<MessageBox> ActiveMessageBoxes = new();
109+
private static readonly List<MessageBox> ActiveMessageBoxes = new();
110110
private static readonly Stack<MessageBox> PooledMessageBoxes = new();
111111

112112
private const int MaxPoolSize = 10;
@@ -145,7 +145,7 @@ internal static bool TestSimulateButtonClick(bool clickOk)
145145
if (ActiveMessageBoxes.Count == 0) return false;
146146

147147
// Get the first message box (any will do for testing)
148-
var target = ActiveMessageBoxes.First();
148+
var target = ActiveMessageBoxes[0];
149149
target.HandleEvent(clickOk);
150150
return true;
151151
}
@@ -158,7 +158,7 @@ internal static (bool okVisible, bool noVisible)? TestGetButtonVisibility()
158158
{
159159
if (ActiveMessageBoxes.Count == 0) return null;
160160

161-
var target = ActiveMessageBoxes.First();
161+
var target = ActiveMessageBoxes[0];
162162
if (target._buttonOk == null || target._buttonNo == null)
163163
return null;
164164

@@ -173,7 +173,7 @@ internal static (string title, string content, string okText, string noText)? Te
173173
{
174174
if (ActiveMessageBoxes.Count == 0) return null;
175175

176-
var target = ActiveMessageBoxes.First();
176+
var target = ActiveMessageBoxes[0];
177177
return (
178178
target._title?.text,
179179
target._content?.text,
@@ -253,13 +253,22 @@ public static void Dispose()
253253

254254
public static void CloseAll()
255255
{
256-
// Create a copy to avoid modification during iteration
257-
var activeBoxes = new MessageBox[ActiveMessageBoxes.Count];
258-
ActiveMessageBoxes.CopyTo(activeBoxes);
256+
var count = ActiveMessageBoxes.Count;
257+
if (count == 0) return;
259258

260-
foreach (var messageBox in activeBoxes)
259+
// Use ArrayPool to avoid allocation
260+
var activeBoxes = ArrayPool<MessageBox>.Shared.Rent(count);
261+
try
262+
{
263+
ActiveMessageBoxes.CopyTo(activeBoxes, 0);
264+
for (var i = 0; i < count; i++)
265+
{
266+
activeBoxes[i].CancelAndClose();
267+
}
268+
}
269+
finally
261270
{
262-
messageBox.CancelAndClose();
271+
ArrayPool<MessageBox>.Shared.Return(activeBoxes, clearArray: true);
263272
}
264273
}
265274

0 commit comments

Comments
 (0)