From a92c9d2cea55577438a49906ed45754bfcff8c1b Mon Sep 17 00:00:00 2001 From: cneicy Date: Tue, 29 Sep 2026 10:14:45 +0800 Subject: [PATCH] perf(eventbus): remove inline allocations and expose binding snapshots --- CodeGen/Editor/EventBusILPostProcessor.cs | 4 ++-- DotNet~/ShrinkSDK.EventBus.csproj | 4 ++-- README.md | 10 ++++++++++ Runtime/EventBus.cs | 8 ++++++++ Runtime/ShrinkEventBusCore.cs | 10 ++++++++++ Runtime/ShrinkEventBusInstance.cs | 20 ++++++++++++++++---- package.json | 4 ++-- 7 files changed, 50 insertions(+), 10 deletions(-) diff --git a/CodeGen/Editor/EventBusILPostProcessor.cs b/CodeGen/Editor/EventBusILPostProcessor.cs index f920898..b53c511 100644 --- a/CodeGen/Editor/EventBusILPostProcessor.cs +++ b/CodeGen/Editor/EventBusILPostProcessor.cs @@ -11,8 +11,8 @@ namespace ShrinkEventBus.CodeGen { public override ILPostProcessor GetInstance() => this; - public override bool WillProcess(ICompiledAssembly compiledAssembly) => - UnityShrinkCodeGenAdapter.ReferencesAny(compiledAssembly, "ShrinkEventBus.Runtime"); + // ShrinkRegistryILPostProcessor owns the complete pass, including event bindings. + public override bool WillProcess(ICompiledAssembly compiledAssembly) => false; public override ILPostProcessResult Process(ICompiledAssembly compiledAssembly) => WillProcess(compiledAssembly) diff --git a/DotNet~/ShrinkSDK.EventBus.csproj b/DotNet~/ShrinkSDK.EventBus.csproj index 3f61641..67c10a5 100644 --- a/DotNet~/ShrinkSDK.EventBus.csproj +++ b/DotNet~/ShrinkSDK.EventBus.csproj @@ -5,7 +5,7 @@ ShrinkEventBus.Runtime ShrinkEventBus ShrinkSDK.EventBus - 2.1.0 + 2.2.2 ShrinkSDK typed event bus runtime. false @@ -13,7 +13,7 @@ - + diff --git a/README.md b/README.md index d16d261..9617ca0 100644 --- a/README.md +++ b/README.md @@ -182,3 +182,13 @@ ShrinkEventBusBenchmark.Run( - Editor 诊断是可选观察层,不参与正式无诊断热路径。 架构审计与来源说明见 `Docs/JustAnyProjectArchitectureAudit.md` 和根目录 `DESIGN.md`。 + +## 可复用能力 + + +Capability: 按类型发布事实和请求,支持同步、异步、优先级和可撤回订阅 +Aliases: 事件 事件未触发 消息 订阅 通知 event bus +Limits: EventBus 不等于业务状态机或资源计量;并行派发须由业务明确选择 +Extension: IShrinkEvent、ShrinkSubscribe、BusOptions 和拥有者 Attach/Dispose +Evidence: [EventBus](Runtime/EventBus.cs); [ShrinkSubscribeAttribute](Runtime/ShrinkEventAttributes.cs); [ShrinkGeneratedBinding](Runtime/ShrinkEventBindings.cs) + diff --git a/Runtime/EventBus.cs b/Runtime/EventBus.cs index 5e611ff..caea5f3 100644 --- a/Runtime/EventBus.cs +++ b/Runtime/EventBus.cs @@ -143,6 +143,14 @@ namespace ShrinkEventBus return generated.AttachGenerated(Resolver, defaultBus ?? ShrinkBusKey.Game); } + public static IReadOnlyList<(Type EventType, System.Reflection.MethodInfo Handler)> CaptureBindings(IShrinkEventBus bus) + { + if (bus is ShrinkEventBusInstance instance) return instance.CaptureBindings(); + throw new NotSupportedException("This event bus does not expose binding diagnostics."); + } + + public static IReadOnlyList CaptureNamedBuses() => new List(Buses.Values); + internal static IReadOnlyList<(ShrinkBusKey Key, ShrinkBusOptions Options, int Subscribers)> Snapshot() { var snapshot = new List<(ShrinkBusKey, ShrinkBusOptions, int)>(Buses.Count); diff --git a/Runtime/ShrinkEventBusCore.cs b/Runtime/ShrinkEventBusCore.cs index af3fdb6..e004126 100644 --- a/Runtime/ShrinkEventBusCore.cs +++ b/Runtime/ShrinkEventBusCore.cs @@ -14,6 +14,7 @@ namespace ShrinkEventBus internal interface IShrinkEventChannel { int Count { get; } + void CaptureBindings(List<(Type EventType, System.Reflection.MethodInfo Handler)> bindings); bool RemoveSubscription(long subscriptionId); void Clear(); void DetachSlot(int slot); @@ -87,6 +88,15 @@ namespace ShrinkEventBus private Action? _syncDispatcher; public int Count => _snapshot.Length; + public void CaptureBindings(List<(Type EventType, System.Reflection.MethodInfo Handler)> bindings) + { + var snapshot = _snapshot; + foreach (var entry in snapshot) + { + var method = entry.SyncHandler?.Method ?? entry.AsyncHandler?.Method; + if (method != null) bindings.Add((typeof(TEvent), method)); + } + } public void Add(long subscriptionId, long registrationOrder, Action handler, ShrinkSubscribeDescriptor descriptor) diff --git a/Runtime/ShrinkEventBusInstance.cs b/Runtime/ShrinkEventBusInstance.cs index bff0246..5465f2a 100644 --- a/Runtime/ShrinkEventBusInstance.cs +++ b/Runtime/ShrinkEventBusInstance.cs @@ -75,7 +75,7 @@ namespace ShrinkEventBus [MethodImpl(MethodImplOptions.AggressiveInlining)] public virtual ShrinkPostResult Post(in TEvent eventData) where TEvent : IShrinkEvent { - if (eventData is null) + if (!typeof(TEvent).IsValueType && eventData is null) throw new ArgumentNullException(nameof(eventData)); if (Volatile.Read(ref _disposed) != 0) return TraceWithoutDispatch(in eventData, @@ -84,6 +84,11 @@ namespace ShrinkEventBus if (_isInline || _scheduler.IsOnSchedulerThread) return Dispatch(in eventData); + return PostScheduled(in eventData); + } + + private ShrinkPostResult PostScheduled(in TEvent eventData) where TEvent : IShrinkEvent + { var queuedEvent = eventData; if (_scheduler.TryPost(() => Dispatch(in queuedEvent))) return new ShrinkPostResult(true, false, false); @@ -94,7 +99,7 @@ namespace ShrinkEventBus public virtual UniTask PostAsync(TEvent eventData, CancellationToken cancellationToken = default) where TEvent : IShrinkEvent { - if (eventData is null) + if (!typeof(TEvent).IsValueType && eventData is null) throw new ArgumentNullException(nameof(eventData)); if (Volatile.Read(ref _disposed) != 0) return UniTask.FromResult(TraceWithoutDispatch(in eventData, @@ -168,6 +173,13 @@ namespace ShrinkEventBus return new EventSubscription(this, subscriptionId); } + internal IReadOnlyList<(Type EventType, System.Reflection.MethodInfo Handler)> CaptureBindings() + { + var bindings = new List<(Type, System.Reflection.MethodInfo)>(); + lock (_channelGate) foreach (var channel in _channels.Values) channel.CaptureBindings(bindings); + return bindings; + } + internal int SubscriberCount { get @@ -367,7 +379,7 @@ namespace ShrinkEventBus [MethodImpl(MethodImplOptions.AggressiveInlining)] public override ShrinkPostResult Post(in TEvent eventData) { - if (eventData is null) + if (!typeof(TEvent).IsValueType && eventData is null) throw new ArgumentNullException(nameof(eventData)); if (IsDisposed) return TraceWithoutDispatch(in eventData, @@ -378,7 +390,7 @@ namespace ShrinkEventBus public override UniTask PostAsync(TEvent eventData, CancellationToken cancellationToken = default) { - if (eventData is null) + if (!typeof(TEvent).IsValueType && eventData is null) throw new ArgumentNullException(nameof(eventData)); if (IsDisposed) return UniTask.FromResult(TraceWithoutDispatch(in eventData, diff --git a/package.json b/package.json index 7c5da1e..4b7e866 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "com.cneicy.shrink-eventbus", - "version": "2.1.0", + "version": "2.2.2", "displayName": "ShrinkEventBus", "description": "多 Bus、特性强类型注册、UniTask 调度与低分配发布的 Unity 事件总线。", "unity": "2022.3", @@ -10,7 +10,7 @@ "dependencies": { "com.cysharp.unitask": "2.5.10", "com.unity.nuget.mono-cecil": "1.11.4", - "com.cneicy.shrink-shared-codegen": "0.1.1", + "com.cneicy.shrink-shared-codegen": "0.2.1", "com.cneicy.shrink-runtime-abstractions": "0.1.0" }, "keywords": [