perf: ListenerList

This commit is contained in:
cneicy committed 2026-03-08 16:57:30 +08:00
1 parent 98acdda3b2
commit f64289406f
3 files changed
+68 -45

No files matched your search

+1 -1
View File
@@ -10,7 +10,7 @@ namespace ShrinkEventBus
public static class EventBus public static class EventBus
{ {
#if UNITY_EDITOR #if UNITY_EDITOR
public static bool EnableDebugRecord { get; set; } = true; public static bool EnableDebugRecord { get; set; }
public static event Action<EventBase, string, string> OnEventTriggeredForEditor; public static event Action<EventBase, string, string> OnEventTriggeredForEditor;
#endif #endif
+66 -43
View File
@@ -1,5 +1,6 @@
#nullable enable #nullable enable
using System; using System;
using System.Collections.Generic;
using System.Reflection; using System.Reflection;
namespace ShrinkEventBus namespace ShrinkEventBus
@@ -7,90 +8,112 @@ namespace ShrinkEventBus
public class ListenerList public class ListenerList
{ {
private readonly object _lock = new(); private readonly object _lock = new();
private EventHandlerInfo[] _handlers = Array.Empty<EventHandlerInfo>();
private readonly List<EventHandlerInfo> _list = new();
private EventHandlerInfo[] _snapshot = Array.Empty<EventHandlerInfo>();
private bool _dirty;
public void Add(Delegate handler, EventPriority priority, int numericPriority, public void Add(Delegate handler, EventPriority priority, int numericPriority,
bool receiveCanceled, string debugInfo = "", MethodInfo? originalMethod = null) bool receiveCanceled, string debugInfo = "", MethodInfo? originalMethod = null)
{ {
var newInfo = new EventHandlerInfo(handler, priority, numericPriority,
receiveCanceled, debugInfo, originalMethod);
lock (_lock) lock (_lock)
{ {
var newInfo = new EventHandlerInfo(handler, priority, numericPriority, var index = BinarySearchInsertIndex(priority, numericPriority);
receiveCanceled, debugInfo, originalMethod); _list.Insert(index, newInfo);
var newArray = new EventHandlerInfo[_handlers.Length + 1]; _dirty = true;
Array.Copy(_handlers, newArray, _handlers.Length);
newArray[^1] = newInfo;
Array.Sort(newArray, CompareHandlers);
_handlers = newArray;
} }
} }
public bool Remove(Delegate handler) public bool Remove(Delegate handler)
{ {
lock (_lock) lock (_lock)
{ {
var index = -1; for (var i = 0; i < _list.Count; i++)
for (var i = 0; i < _handlers.Length; i++)
{ {
if (_handlers[i].Handler.Equals(handler)) if (_list[i].Handler.Equals(handler))
{ {
index = i; _list.RemoveAt(i);
break; _dirty = true;
return true;
} }
} }
return false;
if (index == -1) return false;
var newArray = new EventHandlerInfo[_handlers.Length - 1];
if (index > 0) Array.Copy(_handlers, 0, newArray, 0, index);
if (index < _handlers.Length - 1)
Array.Copy(_handlers, index + 1, newArray, index, _handlers.Length - index - 1);
_handlers = newArray;
return true;
} }
} }
public void RemoveTarget(object target) public void RemoveTarget(object target)
{ {
lock (_lock) lock (_lock)
{ {
var removeCount = 0; var removed = false;
for (var i = 0; i < _handlers.Length; i++) for (var i = _list.Count - 1; i >= 0; i--)
{ {
if (_handlers[i].Target == target) removeCount++; if (_list[i].Target == target)
}
if (removeCount == 0) return;
var newArray = new EventHandlerInfo[_handlers.Length - removeCount];
var dst = 0;
for (var i = 0; i < _handlers.Length; i++)
{
if (_handlers[i].Target != target)
{ {
newArray[dst++] = _handlers[i]; _list.RemoveAt(i);
removed = true;
} }
} }
if (removed) _dirty = true;
_handlers = newArray;
} }
} }
public EventHandlerInfo[] GetHandlers() => _handlers; public EventHandlerInfo[] GetHandlers()
{
lock (_lock)
{
if (_dirty)
{
_snapshot = _list.ToArray();
_dirty = false;
}
return _snapshot;
}
}
public int Count => _handlers.Length; public int Count
{
get { lock (_lock) return _list.Count; }
}
public void Clear() public void Clear()
{ {
lock (_lock) lock (_lock)
{ {
_handlers = Array.Empty<EventHandlerInfo>(); _list.Clear();
_snapshot = Array.Empty<EventHandlerInfo>();
_dirty = false;
} }
} }
private static int CompareHandlers(EventHandlerInfo a, EventHandlerInfo b) private int BinarySearchInsertIndex(EventPriority priority, int numericPriority)
{ {
var priorityCompare = a.Priority.CompareTo(b.Priority); var lo = 0;
return priorityCompare != 0 ? priorityCompare : b.NumericPriority.CompareTo(a.NumericPriority); var hi = _list.Count;
while (lo < hi)
{
var mid = (lo + hi) >> 1;
var existing = _list[mid];
var cmp = existing.Priority.CompareTo(priority);
if (cmp == 0)
cmp = numericPriority.CompareTo(existing.NumericPriority); // 降序
if (cmp < 0)
lo = mid + 1;
else
hi = mid;
}
return lo;
} }
} }
} }
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "com.cneicy.shrink-eventbus", "name": "com.cneicy.shrink-eventbus",
"version": "1.0.0", "version": "1.1.0",
"displayName": "ShrinkEventBus", "displayName": "ShrinkEventBus",
"description": "高性能、类型安全的 Unity 事件总线,支持优先级调度与自动注册。", "description": "高性能、类型安全的 Unity 事件总线,支持优先级调度与自动注册。",
"unity": "2022.3", "unity": "2022.3",