perf: no wrapper

This commit is contained in:
cneicy committed 2026-03-09 17:42:06 +08:00
1 parent 67a8216c64
commit c15c14e394
4 files changed
+33 -113

No files matched your search

+18 -36
View File
@@ -26,16 +26,6 @@ namespace ShrinkEventBus
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
private static void EnsureAutoManagerInitialized() => EventAutoRegHelper.EnsureInitialized(); private static void EnsureAutoManagerInitialized() => EventAutoRegHelper.EnsureInitialized();
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void RegisterEvent<TEvent>(Action<TEvent> handler, string methodName, Type declaringType,
EventPriority priority = EventPriority.NORMAL, bool receiveCanceled = false) where TEvent : EventBase
{
var methodInfo = declaringType.GetMethod(methodName,
BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static);
RegisterEventInternal(typeof(TEvent), handler, priority, 0, receiveCanceled,
$"Manual Sync Handler (Priority: {priority})", methodInfo);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void RegisterEvent<TEvent>(Func<TEvent, UniTask> handler, int priority = 0) public static void RegisterEvent<TEvent>(Func<TEvent, UniTask> handler, int priority = 0)
where TEvent : EventBase where TEvent : EventBase
@@ -184,11 +174,21 @@ namespace ShrinkEventBus
} }
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static bool TryPrepareHandler<TEvent>(TEvent eventArgs, EventHandlerInfo handlerInfo)
where TEvent : EventBase
{
eventArgs.CurrentHandler = handlerInfo;
eventArgs.SetPhase(handlerInfo.Priority);
if (eventArgs.IsCancelable && eventArgs.IsCanceled && !handlerInfo.ReceiveCanceled)
return false;
return true;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static async UniTask<bool> TriggerEventAsync<TEvent>(TEvent eventArgs) where TEvent : EventBase public static async UniTask<bool> TriggerEventAsync<TEvent>(TEvent eventArgs) where TEvent : EventBase
{ {
EnsureAutoManagerInitialized(); EnsureAutoManagerInitialized();
var collection = EventCache<TEvent>.List; var collection = EventCache<TEvent>.List;
if (collection == null) return false; if (collection == null) return false;
@@ -202,10 +202,7 @@ namespace ShrinkEventBus
for (var i = 0; i < handlers.Length; i++) for (var i = 0; i < handlers.Length; i++)
{ {
var handlerInfo = handlers[i]; var handlerInfo = handlers[i];
eventArgs.CurrentHandler = handlerInfo; if (!TryPrepareHandler(eventArgs, handlerInfo)) continue;
eventArgs.SetPhase(handlerInfo.Priority);
if (eventArgs is { IsCancelable: true, IsCanceled: true } && !handlerInfo.ReceiveCanceled) continue;
try try
{ {
@@ -223,8 +220,7 @@ namespace ShrinkEventBus
catch (Exception ex) catch (Exception ex)
{ {
Debug.LogException(ex); Debug.LogException(ex);
Debug.LogError( Debug.LogError($"[EventBus] Async Handler Exception: {ex.Message}");
$"[EventBus] {typeof(TEvent).Name} Async Handler {handlerInfo.DisplayDeclaringType.Name}.{handlerInfo.DisplayMethodName} Exception: {ex.Message}");
} }
} }
@@ -236,7 +232,6 @@ namespace ShrinkEventBus
public static bool TriggerEvent<TEvent>(TEvent eventArgs) where TEvent : EventBase public static bool TriggerEvent<TEvent>(TEvent eventArgs) where TEvent : EventBase
{ {
EnsureAutoManagerInitialized(); EnsureAutoManagerInitialized();
var collection = EventCache<TEvent>.List; var collection = EventCache<TEvent>.List;
if (collection == null) return false; if (collection == null) return false;
@@ -250,10 +245,7 @@ namespace ShrinkEventBus
for (var i = 0; i < handlers.Length; i++) for (var i = 0; i < handlers.Length; i++)
{ {
var handlerInfo = handlers[i]; var handlerInfo = handlers[i];
eventArgs.CurrentHandler = handlerInfo; if (!TryPrepareHandler(eventArgs, handlerInfo)) continue;
eventArgs.SetPhase(handlerInfo.Priority);
if (eventArgs is { IsCancelable: true, IsCanceled: true } && !handlerInfo.ReceiveCanceled) continue;
try try
{ {
@@ -272,8 +264,7 @@ namespace ShrinkEventBus
catch (Exception ex) catch (Exception ex)
{ {
Debug.LogException(ex); Debug.LogException(ex);
Debug.LogError( Debug.LogError($"[EventBus] Sync Handler Exception: {ex.Message}");
$"[EventBus] {typeof(TEvent).Name} Sync Handler {handlerInfo.DisplayDeclaringType.Name}.{handlerInfo.DisplayMethodName} Exception: {ex.Message}");
} }
} }
@@ -311,19 +302,13 @@ namespace ShrinkEventBus
{ {
var method = trace.GetFrame(i)?.GetMethod(); var method = trace.GetFrame(i)?.GetMethod();
var declaringType = method?.DeclaringType; var declaringType = method?.DeclaringType;
if (declaringType == null) continue; if (declaringType == null) continue;
if (declaringType == typeof(EventBus) || if (declaringType == typeof(EventBus) || declaringType.DeclaringType == typeof(EventBus)) continue;
declaringType.DeclaringType == typeof(EventBus)) continue;
var ns = declaringType.Namespace ?? ""; var ns = declaringType.Namespace ?? "";
if (ns.StartsWith("System") || ns.StartsWith("Cysharp") || ns.StartsWith("UnityEngine")) if (ns.StartsWith("System") || ns.StartsWith("Cysharp") || ns.StartsWith("UnityEngine")) continue;
continue;
var className = declaringType.Name; var className = declaringType.Name;
var methodName = method.Name; var methodName = method.Name;
if (declaringType.DeclaringType != null && className.StartsWith("<") && className.Contains(">"))
if (declaringType.DeclaringType != null && className.StartsWith("<") &&
className.Contains(">"))
{ {
className = declaringType.DeclaringType.Name; className = declaringType.DeclaringType.Name;
var startIndex = declaringType.Name.IndexOf('<') + 1; var startIndex = declaringType.Name.IndexOf('<') + 1;
@@ -337,7 +322,6 @@ namespace ShrinkEventBus
} }
catch catch
{ {
// ignored
} }
return senderInfo; return senderInfo;
@@ -370,9 +354,7 @@ namespace ShrinkEventBus
{ {
if (target == null) return; if (target == null) return;
if (IsInstanceRegistered(target)) return; if (IsInstanceRegistered(target)) return;
EventBusRegHelper.RegisterEventHandlers(target); EventBusRegHelper.RegisterEventHandlers(target);
lock (InstanceLock) lock (InstanceLock)
{ {
if (!RegisteredInstances.Add(target)) return; if (!RegisteredInstances.Add(target)) return;
+5 -58
View File
@@ -1,7 +1,6 @@
using System; using System;
using System.Reflection; using System.Reflection;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Threading.Tasks;
using Cysharp.Threading.Tasks; using Cysharp.Threading.Tasks;
using UnityEngine; using UnityEngine;
@@ -54,17 +53,13 @@ namespace ShrinkEventBus
foreach (var method in methods) foreach (var method in methods)
{ {
if (target != null && method.IsStatic) continue; if (target != null && method.IsStatic) continue;
var attributes = method.GetCustomAttributes(typeof(EventSubscribeAttribute), false); var attributes = method.GetCustomAttributes(typeof(EventSubscribeAttribute), false);
if (attributes.Length == 0) continue; if (attributes.Length == 0) continue;
var subscribeAttr = (EventSubscribeAttribute)attributes[0]; var subscribeAttr = (EventSubscribeAttribute)attributes[0];
var parameters = method.GetParameters(); var parameters = method.GetParameters();
if (parameters.Length != 1) continue; if (parameters.Length != 1) continue;
var parameterType = parameters[0].ParameterType; var parameterType = parameters[0].ParameterType;
if (!typeof(EventBase).IsAssignableFrom(parameterType)) continue; if (!typeof(EventBase).IsAssignableFrom(parameterType)) continue;
ProcessMethodRegistration(target, method, subscribeAttr, parameterType); ProcessMethodRegistration(target, method, subscribeAttr, parameterType);
} }
} }
@@ -87,17 +82,6 @@ namespace ShrinkEventBus
subscribeAttr.NumericPriority, subscribeAttr.ReceiveCanceled, subscribeAttr.NumericPriority, subscribeAttr.ReceiveCanceled,
$"{scope} {typeName}.{method.Name} (UniTask)", method); $"{scope} {typeName}.{method.Name} (UniTask)", method);
} }
else if (method.ReturnType == typeof(Task))
{
var funcType = typeof(Func<,>).MakeGenericType(parameterType, typeof(Task));
var handlerDelegate = target == null
? Delegate.CreateDelegate(funcType, method)
: Delegate.CreateDelegate(funcType, target, method);
var wrappedHandler = WrapTaskHandlerWithMethodInfo(parameterType, handlerDelegate, method);
EventBus.RegisterEventInternal(parameterType, wrappedHandler, subscribeAttr.Priority,
subscribeAttr.NumericPriority, subscribeAttr.ReceiveCanceled,
$"{scope} {typeName}.{method.Name} (Task->UniTask)", method);
}
else if (method.ReturnType == typeof(void)) else if (method.ReturnType == typeof(void))
{ {
var actionType = typeof(Action<>).MakeGenericType(parameterType); var actionType = typeof(Action<>).MakeGenericType(parameterType);
@@ -108,6 +92,11 @@ namespace ShrinkEventBus
subscribeAttr.NumericPriority, subscribeAttr.ReceiveCanceled, subscribeAttr.NumericPriority, subscribeAttr.ReceiveCanceled,
$"{scope} {typeName}.{method.Name} (Sync)", method); $"{scope} {typeName}.{method.Name} (Sync)", method);
} }
else
{
Debug.LogWarning(
$"[EventBus] Registration failed: {typeName}.{method.Name} return type must be void or UniTask.");
}
} }
catch (Exception ex) catch (Exception ex)
{ {
@@ -116,47 +105,5 @@ namespace ShrinkEventBus
#endif #endif
} }
} }
private static Delegate WrapTaskHandlerWithMethodInfo(Type eventType, Delegate taskHandler,
MethodInfo originalMethod)
{
var method = typeof(EventBusRegHelper)
.GetMethod(nameof(WrapTaskActionWithMethodInfo), BindingFlags.NonPublic | BindingFlags.Static)
?.MakeGenericMethod(eventType);
return (Delegate)method.Invoke(null, new object[] { taskHandler, originalMethod })!;
}
private static Func<T, UniTask> WrapTaskActionWithMethodInfo<T>(Delegate actionDelegate,
MethodInfo originalMethod)
{
var typedAction = (Func<T, Task>)actionDelegate;
var wrapper = new MethodInfoPreservingTaskWrapper<T>(typedAction, originalMethod);
return wrapper.ExecuteAsync;
}
private class MethodInfoPreservingTaskWrapper<T>
{
private readonly Func<T, Task> _originalAction;
public readonly MethodInfo OriginalMethod;
public MethodInfoPreservingTaskWrapper(Func<T, Task> originalAction, MethodInfo originalMethod)
{
_originalAction = originalAction;
OriginalMethod = originalMethod;
}
public async UniTask ExecuteAsync(T arg)
{
try
{
await _originalAction(arg);
}
catch (Exception ex)
{
Debug.LogException(ex);
Debug.LogError($"[EventBus] Task {OriginalMethod.Name}: {ex.Message}");
}
}
}
} }
} }
+8 -18
View File
@@ -1,10 +1,15 @@
using System; using System;
using System.Reflection; using System.Reflection;
#pragma warning disable CS8632 // 只能在 "#nullable" 注释上下文内的代码中使用可为 null 的引用类型的注释。 #pragma warning disable CS8632 // 只能在 "#nullable" 注释上下文内的代码中使用可为 null 的引用类型的注释。
namespace ShrinkEventBus namespace ShrinkEventBus
{ {
public interface IMethodWrapper
{
MethodInfo OriginalMethod { get; }
}
public class EventHandlerInfo public class EventHandlerInfo
{ {
public Delegate Handler { get; } public Delegate Handler { get; }
@@ -49,24 +54,9 @@ namespace ShrinkEventBus
private static MethodInfo? ExtractOriginalMethodFromWrapper(Delegate handler) private static MethodInfo? ExtractOriginalMethodFromWrapper(Delegate handler)
{ {
if (handler.Target == null) return null; if (handler.Target is IMethodWrapper wrapper)
var targetType = handler.Target.GetType();
if (!targetType.Name.Contains("MethodInfoPreserving")) return null;
try
{ {
var field = targetType.GetField("OriginalMethod", return wrapper.OriginalMethod;
BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
if (field != null) return field.GetValue(handler.Target) as MethodInfo;
var prop = targetType.GetProperty("OriginalMethod",
BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
if (prop != null) return prop.GetValue(handler.Target) as MethodInfo;
}
catch
{
// ignored
} }
return null; return null;
+2 -1
View File
@@ -7,6 +7,7 @@ namespace ShrinkEventBus
{ {
private static readonly Stack<T> Pool = new(32); private static readonly Stack<T> Pool = new(32);
private static readonly object Lock = new(); private static readonly object Lock = new();
private static readonly Action<EventBase> CachedReleaseAction = e => Release((T)e);
public static T Get() public static T Get()
{ {
@@ -21,7 +22,7 @@ namespace ShrinkEventBus
} }
var newEvt = new T(); var newEvt = new T();
newEvt.ReleaseAction = e => Release((T)e); newEvt.ReleaseAction = CachedReleaseAction;
return newEvt; return newEvt;
} }