feat: 重构事件总线为可实例化架构并发布 1.3.0
- 新增 IShrinkEventBus、ShrinkEventBusBuilder 与 ShrinkEventBusInstance,支持独立 bus、异常策略、启动开关、类型校验和按 phase 派发 - 新增 SubscribeEvent 可释放订阅句柄与订阅快照接口,保留 EventBus 静态门面并委托到默认实例 - 重构监听列表为父子事件链共享锁与快照缓存,支持父事件监听子事件、跨父子数字优先级归并和防御性快照拷贝 - 优化 EventBase 元数据缓存、懒生成 EventId、派发快照挂接与对象池双重归还保护,移除旧 EventCache 热路径 - 恢复本地 ILPostProcessor 兜底并生成静态订阅注册表,避免共享 CodeGen 覆盖外程序集自动注册失效 - 改进事件查看器、Benchmark、README 与 CHANGELOG,并新增 Dispatch/Priority/Registration/Subscription 测试覆盖核心行为 BREAKING CHANGE: 移除 EventBase.GetListenerList(),int 数字优先级重载不再提供默认值,数字优先级 0 现在映射为 NORMAL。
This commit is contained in:
41 files changed
+3168
-888
No files matched your search
+274
-75
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using Cysharp.Threading.Tasks;
|
||||
using UnityEngine;
|
||||
@@ -8,39 +9,98 @@ using Debug = UnityEngine.Debug;
|
||||
namespace ShrinkEventBus.Runtime
|
||||
{
|
||||
/// <summary>
|
||||
/// ShrinkEventBus 性能测试
|
||||
/// ShrinkEventBus 性能测试。
|
||||
/// 挂在任意 GameObject 上,运行后在 Console 查看结果。
|
||||
/// 在进行测试时不要打开事件查看器大的追踪实时事件功能
|
||||
/// 在进行测试时不要打开事件查看器的大量实时追踪。
|
||||
/// </summary>
|
||||
public class EventBusBenchmark : MonoBehaviour
|
||||
public sealed class EventBusBenchmark : MonoBehaviour
|
||||
{
|
||||
[Header("同步触发测试")] public int iterations = 1000000;
|
||||
[Header("同步触发测试")] public int iterations = 1_000_000;
|
||||
|
||||
[Header("大批量订阅者测试")] public int subscriberCount = 30;
|
||||
public int massIterations = 1000;
|
||||
public int massIterations = 10_000;
|
||||
|
||||
[Header("异步触发测试")] public int asyncIterations = 1000;
|
||||
[Header("异步触发测试")] public int asyncIterations = 1_000;
|
||||
|
||||
[Header("注册 / 注销测试")] public int registerIterations = 5000;
|
||||
|
||||
[Header("取消事件测试")] public int cancelIterations = 100000;
|
||||
[Header("注册 / 注销测试")] public int registerIterations = 5_000;
|
||||
public int scannedRegisterIterations = 1_000;
|
||||
|
||||
[Header("取消事件测试")] public int cancelIterations = 100_000;
|
||||
|
||||
public class BenchmarkEvent : EventBase
|
||||
{
|
||||
public int Value { get; set; }
|
||||
}
|
||||
|
||||
public sealed class DerivedBenchmarkEvent : BenchmarkEvent
|
||||
{
|
||||
public bool IsDerived { get; set; }
|
||||
}
|
||||
|
||||
[Cancelable]
|
||||
public class CancelableBenchmarkEvent : EventBase
|
||||
{
|
||||
public int Value { get; set; }
|
||||
}
|
||||
|
||||
private sealed class BenchmarkInstanceSubscriber
|
||||
{
|
||||
public int Recorded;
|
||||
|
||||
[EventSubscribe(EventPriority.NORMAL)]
|
||||
private void OnBenchmark(BenchmarkEvent evt)
|
||||
{
|
||||
Recorded = evt.Value;
|
||||
}
|
||||
}
|
||||
|
||||
private static class BenchmarkStaticSubscriber
|
||||
{
|
||||
public static int Recorded;
|
||||
|
||||
[EventSubscribe(EventPriority.NORMAL)]
|
||||
private static void OnBenchmark(BenchmarkEvent evt)
|
||||
{
|
||||
Recorded = evt.Value;
|
||||
}
|
||||
}
|
||||
|
||||
private static class BenchmarkMethodSubscriber
|
||||
{
|
||||
public static int Recorded;
|
||||
|
||||
[EventSubscribe(EventPriority.NORMAL)]
|
||||
private static void OnBenchmark(BenchmarkEvent evt)
|
||||
{
|
||||
Recorded = evt.Value;
|
||||
}
|
||||
}
|
||||
|
||||
private sealed class PhaseSubscriber
|
||||
{
|
||||
public int Sum;
|
||||
|
||||
[EventSubscribe(EventPriority.HIGH)]
|
||||
private void OnHigh(BenchmarkEvent evt)
|
||||
{
|
||||
Sum += evt.Value + 1;
|
||||
}
|
||||
|
||||
[EventSubscribe(EventPriority.NORMAL)]
|
||||
private void OnNormal(BenchmarkEvent evt)
|
||||
{
|
||||
Sum += evt.Value + 10;
|
||||
}
|
||||
|
||||
[EventSubscribe(EventPriority.LOW)]
|
||||
private void OnLow(BenchmarkEvent evt)
|
||||
{
|
||||
Sum += evt.Value + 100;
|
||||
}
|
||||
}
|
||||
|
||||
private readonly StringBuilder _report = new();
|
||||
|
||||
|
||||
private void Start()
|
||||
{
|
||||
RunAllBenchmarks().Forget();
|
||||
@@ -52,8 +112,9 @@ namespace ShrinkEventBus.Runtime
|
||||
_report.AppendLine("╔══════════════════════════════════════════════════╗");
|
||||
_report.AppendLine("║ ShrinkEventBus Benchmark Report ║");
|
||||
_report.AppendLine(
|
||||
$"║ iter={iterations,8} mass={massIterations,5} reg={registerIterations,5} cancel={cancelIterations,6} ║");
|
||||
$"║ iter={iterations,8} mass={massIterations,6} reg={registerIterations,5} scan={scannedRegisterIterations,4} ║");
|
||||
_report.AppendLine("╚══════════════════════════════════════════════════╝");
|
||||
_report.AppendLine(" 基准对象:独立实例 bus(AllowPerPhaseDispatch 已开启)");
|
||||
|
||||
Log("开始:无订阅者触发");
|
||||
Bench_TriggerEvent_NoSubscriber();
|
||||
@@ -63,16 +124,36 @@ namespace ShrinkEventBus.Runtime
|
||||
Bench_TriggerEvent_SingleSubscriber();
|
||||
await UniTask.Yield();
|
||||
|
||||
Log("开始:父事件监听子事件");
|
||||
Bench_TriggerEvent_InheritedSubscriber();
|
||||
await UniTask.Yield();
|
||||
|
||||
Log($"开始:{subscriberCount} 订阅者同步触发");
|
||||
Bench_TriggerEvent_MassSubscribers();
|
||||
await UniTask.Yield();
|
||||
|
||||
Log("开始:按 phase 分发");
|
||||
Bench_TriggerEvent_PerPhase();
|
||||
await UniTask.Yield();
|
||||
|
||||
Log("开始:异步触发");
|
||||
await Bench_TriggerEventAsync();
|
||||
await UniTask.Yield();
|
||||
|
||||
Log("开始:注册/注销");
|
||||
Bench_RegisterUnregister();
|
||||
Log("开始:手工 delegate 注册/注销");
|
||||
Bench_RegisterUnregister_ManualDelegate();
|
||||
await UniTask.Yield();
|
||||
|
||||
Log("开始:实例扫描注册/注销");
|
||||
Bench_RegisterUnregister_InstanceScan();
|
||||
await UniTask.Yield();
|
||||
|
||||
Log("开始:静态类型扫描注册/注销");
|
||||
Bench_RegisterUnregister_StaticScan();
|
||||
await UniTask.Yield();
|
||||
|
||||
Log("开始:MethodInfo 注册/注销");
|
||||
Bench_RegisterUnregister_MethodScan();
|
||||
await UniTask.Yield();
|
||||
|
||||
Log("开始:EventPool vs new");
|
||||
@@ -87,95 +168,141 @@ namespace ShrinkEventBus.Runtime
|
||||
Debug.Log(_report.ToString());
|
||||
}
|
||||
|
||||
|
||||
private void Bench_TriggerEvent_NoSubscriber()
|
||||
{
|
||||
EventBus.ClearAllSubscribersForEvent<BenchmarkEvent>();
|
||||
var bus = CreateBenchmarkBus();
|
||||
var evt = new BenchmarkEvent { Value = 1 };
|
||||
|
||||
for (var i = 0; i < 500; i++) EventBus.TriggerEvent(evt);
|
||||
Warmup(() => bus.TriggerEvent(evt), 500);
|
||||
|
||||
var sw = Stopwatch.StartNew();
|
||||
for (var i = 0; i < iterations; i++) EventBus.TriggerEvent(evt);
|
||||
for (var i = 0; i < iterations; i++)
|
||||
bus.TriggerEvent(evt);
|
||||
sw.Stop();
|
||||
|
||||
Record("TriggerEvent × 无订阅者(基线)", sw.Elapsed.TotalMilliseconds, iterations);
|
||||
Log("完成:无订阅者触发");
|
||||
}
|
||||
|
||||
|
||||
private void Bench_TriggerEvent_SingleSubscriber()
|
||||
{
|
||||
EventBus.ClearAllSubscribersForEvent<BenchmarkEvent>();
|
||||
|
||||
var bus = CreateBenchmarkBus();
|
||||
var dummy = 0;
|
||||
|
||||
void Handler(BenchmarkEvent e)
|
||||
void Handler(BenchmarkEvent evt)
|
||||
{
|
||||
dummy = e.Value;
|
||||
dummy = evt.Value;
|
||||
}
|
||||
|
||||
EventBus.RegisterEvent<BenchmarkEvent>(Handler, EventPriority.NORMAL);
|
||||
bus.RegisterEvent<BenchmarkEvent>(Handler, EventPriority.NORMAL);
|
||||
|
||||
var evt = new BenchmarkEvent { Value = 1 };
|
||||
for (var i = 0; i < 500; i++) EventBus.TriggerEvent(evt);
|
||||
Warmup(() => bus.TriggerEvent(evt), 500);
|
||||
|
||||
var sw = Stopwatch.StartNew();
|
||||
for (var i = 0; i < iterations; i++) EventBus.TriggerEvent(evt);
|
||||
for (var i = 0; i < iterations; i++)
|
||||
bus.TriggerEvent(evt);
|
||||
sw.Stop();
|
||||
|
||||
Record("TriggerEvent × 单订阅者同步", sw.Elapsed.TotalMilliseconds, iterations);
|
||||
Log("完成:单订阅者同步触发");
|
||||
|
||||
EventBus.UnregisterEvent<BenchmarkEvent>(Handler);
|
||||
bus.UnregisterEvent<BenchmarkEvent>(Handler);
|
||||
GC.KeepAlive(dummy);
|
||||
}
|
||||
|
||||
private void Bench_TriggerEvent_InheritedSubscriber()
|
||||
{
|
||||
var bus = CreateBenchmarkBus();
|
||||
var dummy = 0;
|
||||
|
||||
void Handler(BenchmarkEvent evt)
|
||||
{
|
||||
dummy = evt.Value;
|
||||
}
|
||||
|
||||
bus.RegisterEvent<BenchmarkEvent>(Handler, EventPriority.NORMAL);
|
||||
|
||||
var evt = new DerivedBenchmarkEvent { Value = 1, IsDerived = true };
|
||||
Warmup(() => bus.TriggerEvent(evt), 500);
|
||||
|
||||
var sw = Stopwatch.StartNew();
|
||||
for (var i = 0; i < iterations; i++)
|
||||
bus.TriggerEvent(evt);
|
||||
sw.Stop();
|
||||
|
||||
Record("TriggerEvent × 父事件监听子事件", sw.Elapsed.TotalMilliseconds, iterations);
|
||||
Log("完成:父事件监听子事件");
|
||||
|
||||
bus.UnregisterEvent<BenchmarkEvent>(Handler);
|
||||
GC.KeepAlive(dummy);
|
||||
}
|
||||
|
||||
private void Bench_TriggerEvent_MassSubscribers()
|
||||
{
|
||||
EventBus.ClearAllSubscribersForEvent<BenchmarkEvent>();
|
||||
|
||||
var bus = CreateBenchmarkBus();
|
||||
var dummy = 0;
|
||||
var handlers = new Action<BenchmarkEvent>[subscriberCount];
|
||||
for (var i = 0; i < subscriberCount; i++)
|
||||
{
|
||||
var captured = i;
|
||||
handlers[i] = e => { dummy = captured + e.Value; };
|
||||
EventBus.RegisterEvent<BenchmarkEvent>(handlers[i], EventPriority.NORMAL);
|
||||
handlers[i] = evt => { dummy = captured + evt.Value; };
|
||||
bus.RegisterEvent<BenchmarkEvent>(handlers[i], EventPriority.NORMAL);
|
||||
}
|
||||
|
||||
var evt = new BenchmarkEvent { Value = 1 };
|
||||
for (var i = 0; i < 100; i++) EventBus.TriggerEvent(evt);
|
||||
Warmup(() => bus.TriggerEvent(evt), 100);
|
||||
|
||||
var sw = Stopwatch.StartNew();
|
||||
for (var i = 0; i < massIterations; i++) EventBus.TriggerEvent(evt);
|
||||
for (var i = 0; i < massIterations; i++)
|
||||
bus.TriggerEvent(evt);
|
||||
sw.Stop();
|
||||
|
||||
Record($"TriggerEvent × {subscriberCount} 订阅者同步", sw.Elapsed.TotalMilliseconds, massIterations);
|
||||
Log($"完成:{subscriberCount} 订阅者同步触发");
|
||||
|
||||
foreach (var h in handlers) EventBus.UnregisterEvent<BenchmarkEvent>(h);
|
||||
foreach (var handler in handlers)
|
||||
bus.UnregisterEvent<BenchmarkEvent>(handler);
|
||||
|
||||
GC.KeepAlive(dummy);
|
||||
}
|
||||
|
||||
private void Bench_TriggerEvent_PerPhase()
|
||||
{
|
||||
var bus = CreateBenchmarkBus();
|
||||
var subscriber = new PhaseSubscriber();
|
||||
bus.Register(subscriber);
|
||||
|
||||
var evt = new BenchmarkEvent { Value = 1 };
|
||||
Warmup(() => bus.TriggerEvent(EventPriority.HIGH, evt), 500);
|
||||
|
||||
var sw = Stopwatch.StartNew();
|
||||
for (var i = 0; i < iterations; i++)
|
||||
bus.TriggerEvent(EventPriority.HIGH, evt);
|
||||
sw.Stop();
|
||||
|
||||
Record("TriggerEvent(Phase=HIGH) × 3 phase 监听", sw.Elapsed.TotalMilliseconds, iterations);
|
||||
Log("完成:按 phase 分发");
|
||||
|
||||
bus.Unregister(subscriber);
|
||||
GC.KeepAlive(subscriber.Sum);
|
||||
}
|
||||
|
||||
private async UniTask Bench_TriggerEventAsync()
|
||||
{
|
||||
EventBus.ClearAllSubscribersForEvent<BenchmarkEvent>();
|
||||
|
||||
var bus = CreateBenchmarkBus();
|
||||
var dummy = 0;
|
||||
|
||||
async UniTask Handler(BenchmarkEvent e)
|
||||
async UniTask Handler(BenchmarkEvent evt)
|
||||
{
|
||||
dummy = e.Value;
|
||||
dummy = evt.Value;
|
||||
await UniTask.CompletedTask;
|
||||
}
|
||||
|
||||
EventBus.RegisterEvent<BenchmarkEvent>(Handler, EventPriority.NORMAL);
|
||||
bus.RegisterEvent<BenchmarkEvent>(Handler, EventPriority.NORMAL);
|
||||
|
||||
var evt = new BenchmarkEvent { Value = 1 };
|
||||
for (var i = 0; i < 10; i++) await EventBus.TriggerEventAsync(evt);
|
||||
await WarmupAsync(() => bus.TriggerEventAsync(evt), 10);
|
||||
|
||||
const int perFrame = 10;
|
||||
var totalMs = 0.0;
|
||||
@@ -186,7 +313,8 @@ namespace ShrinkEventBus.Runtime
|
||||
await UniTask.Yield();
|
||||
var count = Math.Min(perFrame, asyncIterations - ran);
|
||||
var sw = Stopwatch.StartNew();
|
||||
for (var i = 0; i < count; i++) await EventBus.TriggerEventAsync(evt);
|
||||
for (var i = 0; i < count; i++)
|
||||
await bus.TriggerEventAsync(evt);
|
||||
sw.Stop();
|
||||
totalMs += sw.Elapsed.TotalMilliseconds;
|
||||
ran += count;
|
||||
@@ -195,48 +323,102 @@ namespace ShrinkEventBus.Runtime
|
||||
Record("TriggerEventAsync × 单订阅者异步", totalMs, asyncIterations);
|
||||
Log("完成:异步触发");
|
||||
|
||||
EventBus.UnregisterEvent<BenchmarkEvent>(Handler);
|
||||
bus.UnregisterEvent<BenchmarkEvent>(Handler);
|
||||
GC.KeepAlive(dummy);
|
||||
}
|
||||
|
||||
|
||||
private void Bench_RegisterUnregister()
|
||||
private void Bench_RegisterUnregister_ManualDelegate()
|
||||
{
|
||||
var bus = CreateBenchmarkBus();
|
||||
var dummy = 0;
|
||||
var handlers = new Action<BenchmarkEvent>[registerIterations];
|
||||
for (var i = 0; i < registerIterations; i++)
|
||||
{
|
||||
var captured = i;
|
||||
handlers[i] = e => { dummy = captured; };
|
||||
handlers[i] = evt => { dummy = captured; };
|
||||
}
|
||||
|
||||
var swReg = Stopwatch.StartNew();
|
||||
for (var i = 0; i < registerIterations; i++)
|
||||
EventBus.RegisterEvent<BenchmarkEvent>(handlers[i], EventPriority.NORMAL);
|
||||
bus.RegisterEvent<BenchmarkEvent>(handlers[i], EventPriority.NORMAL);
|
||||
swReg.Stop();
|
||||
Record("RegisterEvent", swReg.Elapsed.TotalMilliseconds, registerIterations);
|
||||
Log("完成:RegisterEvent");
|
||||
Record("RegisterEvent(delegate)", swReg.Elapsed.TotalMilliseconds, registerIterations);
|
||||
|
||||
var swUnreg = Stopwatch.StartNew();
|
||||
for (var i = 0; i < registerIterations; i++)
|
||||
EventBus.UnregisterEvent<BenchmarkEvent>(handlers[i]);
|
||||
bus.UnregisterEvent<BenchmarkEvent>(handlers[i]);
|
||||
swUnreg.Stop();
|
||||
Record("UnregisterEvent", swUnreg.Elapsed.TotalMilliseconds, registerIterations);
|
||||
Log("完成:UnregisterEvent");
|
||||
Record("UnregisterEvent(delegate)", swUnreg.Elapsed.TotalMilliseconds, registerIterations);
|
||||
Log("完成:手工 delegate 注册/注销");
|
||||
|
||||
GC.KeepAlive(dummy);
|
||||
}
|
||||
|
||||
private void Bench_RegisterUnregister_InstanceScan()
|
||||
{
|
||||
var bus = CreateBenchmarkBus();
|
||||
var subscribers = new BenchmarkInstanceSubscriber[scannedRegisterIterations];
|
||||
for (var i = 0; i < subscribers.Length; i++)
|
||||
subscribers[i] = new BenchmarkInstanceSubscriber();
|
||||
|
||||
var sw = Stopwatch.StartNew();
|
||||
for (var i = 0; i < subscribers.Length; i++)
|
||||
{
|
||||
var subscriber = subscribers[i];
|
||||
bus.Register(subscriber);
|
||||
bus.Unregister(subscriber);
|
||||
}
|
||||
|
||||
sw.Stop();
|
||||
Record("Register/Unregister(instance scan)", sw.Elapsed.TotalMilliseconds, subscribers.Length);
|
||||
Log("完成:实例扫描注册/注销");
|
||||
}
|
||||
|
||||
private void Bench_RegisterUnregister_StaticScan()
|
||||
{
|
||||
var bus = CreateBenchmarkBus();
|
||||
|
||||
var sw = Stopwatch.StartNew();
|
||||
for (var i = 0; i < scannedRegisterIterations; i++)
|
||||
{
|
||||
bus.Register(typeof(BenchmarkStaticSubscriber));
|
||||
bus.Unregister(typeof(BenchmarkStaticSubscriber));
|
||||
}
|
||||
|
||||
sw.Stop();
|
||||
Record("Register/Unregister(static type scan)", sw.Elapsed.TotalMilliseconds, scannedRegisterIterations);
|
||||
Log("完成:静态类型扫描注册/注销");
|
||||
}
|
||||
|
||||
private void Bench_RegisterUnregister_MethodScan()
|
||||
{
|
||||
var bus = CreateBenchmarkBus();
|
||||
var method = typeof(BenchmarkMethodSubscriber).GetMethod("OnBenchmark",
|
||||
BindingFlags.Static | BindingFlags.NonPublic);
|
||||
if (method == null)
|
||||
throw new MissingMethodException(typeof(BenchmarkMethodSubscriber).FullName, "OnBenchmark");
|
||||
|
||||
var sw = Stopwatch.StartNew();
|
||||
for (var i = 0; i < scannedRegisterIterations; i++)
|
||||
{
|
||||
bus.Register(method);
|
||||
bus.Unregister(method);
|
||||
}
|
||||
|
||||
sw.Stop();
|
||||
Record("Register/Unregister(MethodInfo)", sw.Elapsed.TotalMilliseconds, scannedRegisterIterations);
|
||||
Log("完成:MethodInfo 注册/注销");
|
||||
}
|
||||
|
||||
private void Bench_EventPool_vs_New()
|
||||
{
|
||||
EventBus.ClearAllSubscribersForEvent<BenchmarkEvent>();
|
||||
var bus = CreateBenchmarkBus();
|
||||
|
||||
void Handler(BenchmarkEvent e)
|
||||
void Handler(BenchmarkEvent evt)
|
||||
{
|
||||
}
|
||||
|
||||
EventBus.RegisterEvent<BenchmarkEvent>(Handler, EventPriority.NORMAL);
|
||||
bus.RegisterEvent<BenchmarkEvent>(Handler, EventPriority.NORMAL);
|
||||
|
||||
for (var i = 0; i < 64; i++)
|
||||
EventPool<BenchmarkEvent>.Release(EventPool<BenchmarkEvent>.Get());
|
||||
@@ -246,75 +428,92 @@ namespace ShrinkEventBus.Runtime
|
||||
var swNew = Stopwatch.StartNew();
|
||||
for (var i = 0; i < iterations; i++)
|
||||
{
|
||||
var e = new BenchmarkEvent { Value = i };
|
||||
EventBus.TriggerEvent(e);
|
||||
var evt = new BenchmarkEvent { Value = i };
|
||||
bus.TriggerEvent(evt);
|
||||
}
|
||||
|
||||
swNew.Stop();
|
||||
var gcNew = GC.CollectionCount(0) - gcBefore;
|
||||
Record($"TriggerEvent × new() [GC Gen0={gcNew,3}]", swNew.Elapsed.TotalMilliseconds, iterations);
|
||||
Log("完成:new() 分配");
|
||||
|
||||
GC.Collect();
|
||||
gcBefore = GC.CollectionCount(0);
|
||||
var swPool = Stopwatch.StartNew();
|
||||
for (var i = 0; i < iterations; i++)
|
||||
{
|
||||
using var e = EventPool<BenchmarkEvent>.Get();
|
||||
e.Value = i;
|
||||
EventBus.TriggerEvent(e);
|
||||
using var evt = EventPool<BenchmarkEvent>.Get();
|
||||
evt.Value = i;
|
||||
bus.TriggerEvent(evt);
|
||||
}
|
||||
|
||||
swPool.Stop();
|
||||
var gcPool = GC.CollectionCount(0) - gcBefore;
|
||||
Record($"TriggerEvent × Pool.Get() [GC Gen0={gcPool,3}]", swPool.Elapsed.TotalMilliseconds, iterations);
|
||||
Log("完成:Pool.Get()");
|
||||
Log("完成:EventPool vs new");
|
||||
|
||||
EventBus.UnregisterEvent<BenchmarkEvent>(Handler);
|
||||
bus.UnregisterEvent<BenchmarkEvent>(Handler);
|
||||
}
|
||||
|
||||
|
||||
private void Bench_CanceledEvent_Skip()
|
||||
{
|
||||
EventBus.ClearAllSubscribersForEvent<CancelableBenchmarkEvent>();
|
||||
|
||||
var bus = CreateBenchmarkBus();
|
||||
var dummy = 0;
|
||||
var handlers = new Action<CancelableBenchmarkEvent>[10];
|
||||
for (var i = 0; i < 10; i++)
|
||||
for (var i = 0; i < handlers.Length; i++)
|
||||
{
|
||||
handlers[i] = e => { dummy = e.Value; };
|
||||
EventBus.RegisterEvent<CancelableBenchmarkEvent>(handlers[i], EventPriority.NORMAL);
|
||||
handlers[i] = evt => { dummy = evt.Value; };
|
||||
bus.RegisterEvent<CancelableBenchmarkEvent>(handlers[i], EventPriority.NORMAL);
|
||||
}
|
||||
|
||||
var evt = new CancelableBenchmarkEvent { Value = 1 };
|
||||
evt.SetCanceled(true);
|
||||
|
||||
for (var i = 0; i < 500; i++) EventBus.TriggerEvent(evt);
|
||||
Warmup(() => bus.TriggerEvent(evt), 500);
|
||||
|
||||
var sw = Stopwatch.StartNew();
|
||||
for (var i = 0; i < cancelIterations; i++) EventBus.TriggerEvent(evt);
|
||||
for (var i = 0; i < cancelIterations; i++)
|
||||
bus.TriggerEvent(evt);
|
||||
sw.Stop();
|
||||
|
||||
Record("TriggerEvent × 已取消事件跳过(10 订阅者)", sw.Elapsed.TotalMilliseconds, cancelIterations);
|
||||
Log("完成:已取消事件跳过");
|
||||
|
||||
foreach (var h in handlers)
|
||||
EventBus.UnregisterEvent<CancelableBenchmarkEvent>(h);
|
||||
foreach (var handler in handlers)
|
||||
bus.UnregisterEvent<CancelableBenchmarkEvent>(handler);
|
||||
|
||||
GC.KeepAlive(dummy);
|
||||
}
|
||||
|
||||
private static IShrinkEventBus CreateBenchmarkBus()
|
||||
{
|
||||
return EventBus.CreateBus(builder => builder.AllowPerPhaseDispatch());
|
||||
}
|
||||
|
||||
private static void Log(string msg) =>
|
||||
private static void Warmup(Action action, int count)
|
||||
{
|
||||
for (var i = 0; i < count; i++)
|
||||
action();
|
||||
}
|
||||
|
||||
private static async UniTask WarmupAsync(Func<UniTask<bool>> action, int count)
|
||||
{
|
||||
for (var i = 0; i < count; i++)
|
||||
await action();
|
||||
}
|
||||
|
||||
private static void Log(string msg)
|
||||
{
|
||||
Debug.Log($"[Benchmark] {msg}");
|
||||
}
|
||||
|
||||
private void Record(string label, double totalMs, int count)
|
||||
{
|
||||
var perOp = totalMs / count * 1000.0;
|
||||
var throughput = count / (totalMs / 1000.0);
|
||||
var throughput = totalMs <= 0.0001 ? 0 : count / (totalMs / 1000.0);
|
||||
_report.AppendLine($"\n ▶ {label}");
|
||||
_report.AppendLine($" 总耗时 : {totalMs,10:F3} ms");
|
||||
_report.AppendLine($" 单次 : {perOp,10:F4} μs/op");
|
||||
_report.AppendLine($" 吞吐量 : {throughput,10:F0} ops/s");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user