From 819320f355bd273068021dfe2d2a1439b58a58f7 Mon Sep 17 00:00:00 2001 From: fengjiayi <12821976+ning_xi@user.noreply.gitee.com> Date: Sat, 23 Aug 2025 16:19:30 +0800 Subject: [PATCH] =?UTF-8?q?1.=20=E4=BF=AE=E6=94=B9=E4=BA=86Serein.Library?= =?UTF-8?q?=E4=B8=AD=E7=9A=84ObjectPool=E5=B7=A5=E5=85=B7=E7=B1=BB?= =?UTF-8?q?=EF=BC=8C=E6=8F=90=E4=BE=9B=E4=BA=86=E5=AF=B9=E8=B1=A1=E5=BD=92?= =?UTF-8?q?=E8=BF=98=E7=9A=84=E9=BB=98=E8=AE=A4=E5=A4=84=E7=90=86=E6=96=B9?= =?UTF-8?q?=E6=B3=95=EF=BC=88=E9=80=9A=E8=BF=87=E6=9E=84=E9=80=A0=E6=96=B9?= =?UTF-8?q?=E6=B3=95=E6=8C=87=E5=AE=9AAction=E5=A7=94=E6=89=98=EF=BC=89?= =?UTF-8?q?=202.=20=E4=B8=8D=E5=86=8D=E6=98=BE=E5=BC=8F=E8=B0=83=E7=94=A8?= =?UTF-8?q?=E6=B5=81=E7=A8=8B=E4=B8=8A=E4=B8=8B=E6=96=87=E7=9A=84Reset()?= =?UTF-8?q?=E6=96=B9=E6=B3=95=EF=BC=8C=E8=80=8C=E6=94=B9=E4=B8=BA=E9=80=9A?= =?UTF-8?q?=E8=BF=87=E5=AF=B9=E8=B1=A1=E6=B1=A0=E8=B0=83=E7=94=A8=203.=20?= =?UTF-8?q?=E5=90=8C=E6=A0=B7=E7=9A=84=EF=BC=8C=E5=AF=B9=E4=BA=8E=E5=90=8C?= =?UTF-8?q?=E6=A0=B7=E4=BD=BF=E7=94=A8=E4=BA=86ObjectPool=E7=AE=A1?= =?UTF-8?q?=E7=90=86=E4=B8=8A=E4=B8=8B=E6=96=87=E7=9A=84Serein.Proto.WebSo?= =?UTF-8?q?cket=E9=A1=B9=E7=9B=AE=E8=80=8C=E8=A8=80=EF=BC=8C=E4=B9=9F?= =?UTF-8?q?=E8=BF=9B=E8=A1=8C=E4=BA=86=E5=90=8C2.=E4=B8=80=E6=A0=B7?= =?UTF-8?q?=E7=9A=84=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../FlowNode/Env/LightweightFlowControl.cs | 3 ++ Library/Utils/ObjectPool.cs | 43 ++++++++++--------- NodeFlow/Env/FlowControl.cs | 7 +-- NodeFlow/Model/Infos/FlowApiMethodInfo.cs | 3 -- NodeFlow/Tool/FlowWorkManagement.cs | 7 --- .../Handle/WebSocketHandleModule.cs | 2 +- .../SereinWebSocketService.cs | 30 +++++++------ Workbench/Serein.Workbench.csproj | 1 + 8 files changed, 47 insertions(+), 49 deletions(-) diff --git a/Library/FlowNode/Env/LightweightFlowControl.cs b/Library/FlowNode/Env/LightweightFlowControl.cs index e6f361b..2eb0b4d 100644 --- a/Library/FlowNode/Env/LightweightFlowControl.cs +++ b/Library/FlowNode/Env/LightweightFlowControl.cs @@ -41,6 +41,9 @@ namespace Serein.Library FlowContextPool = new Utils.ObjectPool(() => { return new FlowContext(flowEnvironment); + }, context => + { + context.Reset(); }); } diff --git a/Library/Utils/ObjectPool.cs b/Library/Utils/ObjectPool.cs index 2e9ad40..d97f36d 100644 --- a/Library/Utils/ObjectPool.cs +++ b/Library/Utils/ObjectPool.cs @@ -9,16 +9,17 @@ using System.Threading.Tasks; namespace Serein.Library.Utils { /// - /// 具有预定义池大小限制的对象池模式的通用实现。其主要目的是将有限数量的经常使用的对象保留在池中,以便进一步回收。 - /// - /// 注: - /// 1)目标不是保留所有返回的对象。池不是用来存储的。如果池中没有空间,则会丢弃额外返回的对象。 - /// - /// 2)这意味着如果对象是从池中获得的,调用者将在相对较短的时间内返回它 - /// 时间。长时间保持检出对象是可以的,但是会降低池的有用性。你只需要重新开始。 - /// - /// 不将对象返回给池并不会损害池的工作,但这是一种不好的做法。 - /// 基本原理:如果没有重用对象的意图,就不要使用pool——只使用“new” + /// + /// 具有预定义池大小限制的对象池模式的通用实现。其主要目的是将有限数量的经常使用的对象保留在池中,以便进一步回收。 + /// + /// 注: + /// 1)目标不是保留所有返回的对象。池不是用来存储的。如果池中没有空间,则会丢弃额外返回的对象。 + /// + /// 2)这意味着如果对象是从池中获得的,调用者将在相对较短的时间内返回它 + /// 时间。长时间保持检出对象是可以的,但是会降低池的有用性。你只需要重新开始。 + /// + /// 不将对象返回给池并不会损害池的工作,但这是一种不好的做法。 + /// 基本原理:如果没有重用对象的意图,就不要使用pool——只使用“new” /// public class ObjectPool where T : class { @@ -28,12 +29,7 @@ namespace Serein.Library.Utils internal T Value; } - /// - /// 不使用System。Func{T},因为. net 2.0没有该类型。 - /// - /// - public delegate T Factory(); - + /// /// 池对象的存储。第一个项存储在专用字段中,因为我们希望能够满足来自它的大多数请求。 /// @@ -45,14 +41,18 @@ namespace Serein.Library.Utils /// 工厂在池的生命周期内被存储。只有当池需要扩展时,我们才调用它。 /// 与“new T()”相比,Func为实现者提供了更多的灵活性,并且比“new T()”更快。 /// - private readonly Factory _factory; + private readonly Func _factory; + + /// + /// 指定了 T 对象释放时的行为。 + /// + private readonly Action? _free; /// /// 创建一个新的对象池实例,使用指定的工厂函数和默认大小(处理器核心数的两倍)。 /// /// - public ObjectPool(Factory factory) - : this(factory, Environment.ProcessorCount * 2) + public ObjectPool(Func factory, Action? free = null) : this(factory, Environment.ProcessorCount * 2, free) { } @@ -61,10 +61,11 @@ namespace Serein.Library.Utils /// /// /// - public ObjectPool(Factory factory, int size) + public ObjectPool(Func factory, int size, Action? free = null) { Debug.Assert(size >= 1); _factory = factory; + _free = free; _items = new Element[size - 1]; } @@ -136,7 +137,7 @@ namespace Serein.Library.Utils public void Free(T obj) { Validate(obj); - + _free?.Invoke(obj); if (_firstItem == null) { // 这里故意不使用联锁。在最坏的情况下,两个对象可能存储在同一个槽中。这是不太可能发生的,只意味着其中一个对象将被收集。 diff --git a/NodeFlow/Env/FlowControl.cs b/NodeFlow/Env/FlowControl.cs index faed92d..9a374f5 100644 --- a/NodeFlow/Env/FlowControl.cs +++ b/NodeFlow/Env/FlowControl.cs @@ -40,14 +40,14 @@ namespace Serein.NodeFlow.Env this.flowModelService = flowModelService; this.UIContextOperation = UIContextOperation; - contexts = new ObjectPool(() => new FlowContext(flowEnvironment)); + contexts = new ObjectPool(() => new FlowContext(flowEnvironment), context => context.Reset()); flowTaskOptions = new FlowWorkOptions { FlowIOC = IOC, Environment = flowEnvironment, // 流程 FlowContextPool = contexts, // 上下文对象池 }; - flowTaskManagementPool = new ObjectPool(()=> new FlowWorkManagement(flowTaskOptions)); + flowTaskManagementPool = new ObjectPool(()=> new FlowWorkManagement(flowTaskOptions), fwm => fwm.Exit()); } private ObjectPool contexts; @@ -102,7 +102,6 @@ namespace Serein.NodeFlow.Env { flowWorkManagements.Remove(fwm); } - fwm.Exit(); flowTaskManagementPool.Free(fwm); } @@ -257,7 +256,6 @@ namespace Serein.NodeFlow.Env } }); } - context.Reset(); flowContextPool.Free(context); ReturnFWM(flowWorkManagement); // 释放流程任务管理器 if (flowResult.Value is TResult result) @@ -330,7 +328,6 @@ namespace Serein.NodeFlow.Env } }); } - context.Reset(); flowContextPool.Free(context); ReturnFWM(flowWorkManagement); // 释放流程任务管理器 } diff --git a/NodeFlow/Model/Infos/FlowApiMethodInfo.cs b/NodeFlow/Model/Infos/FlowApiMethodInfo.cs index 1fe6195..6527a2d 100644 --- a/NodeFlow/Model/Infos/FlowApiMethodInfo.cs +++ b/NodeFlow/Model/Infos/FlowApiMethodInfo.cs @@ -184,7 +184,6 @@ namespace Serein.NodeFlow.Model.Infos sb.AppendCode(3, $"}}"); sb.AppendCode(3, $"finally"); sb.AppendCode(3, $"{{"); - sb.AppendCode(4, $"{flowContext}.{nameof(IFlowContext.Reset)}(); "); sb.AppendCode(4, $"cts.{nameof(CancellationTokenSource.Dispose)}(); "); sb.AppendCode(4, $"{flowContextPoolName}.{nameof(LightweightFlowControl.FlowContextPool)}.{nameof(LightweightFlowControl.FlowContextPool.Free)}({flowContext}); // 释放上下文"); sb.AppendCode(3, $"}}"); @@ -272,7 +271,6 @@ namespace Serein.NodeFlow.Model.Infos sb.AppendCode(3, $"}}"); sb.AppendCode(3, $"finally"); sb.AppendCode(3, $"{{"); - sb.AppendCode(4, $"{flowContext}.{nameof(IFlowContext.Reset)}(); "); sb.AppendCode(4, $"cts.{nameof(CancellationTokenSource.Dispose)}(); "); sb.AppendCode(4, $"{flowContextPoolName}.{nameof(LightweightFlowControl.FlowContextPool)}.{nameof(LightweightFlowControl.FlowContextPool.Free)}({flowContext}); // 释放上下文"); sb.AppendCode(3, $"}}"); @@ -297,7 +295,6 @@ namespace Serein.NodeFlow.Model.Infos sb.AppendCode(3, $"}}"); sb.AppendCode(3, $"finally"); sb.AppendCode(3, $"{{"); - sb.AppendCode(4, $"{flowContext}.{nameof(IFlowContext.Reset)}(); "); sb.AppendCode(4, $"{flowContextPoolName}.{nameof(LightweightFlowControl.FlowContextPool)}.{nameof(LightweightFlowControl.FlowContextPool.Free)}({flowContext}); // 释放上下文"); sb.AppendCode(3, $"}}"); sb.AppendCode(2, $"}}"); diff --git a/NodeFlow/Tool/FlowWorkManagement.cs b/NodeFlow/Tool/FlowWorkManagement.cs index 59010ff..303e626 100644 --- a/NodeFlow/Tool/FlowWorkManagement.cs +++ b/NodeFlow/Tool/FlowWorkManagement.cs @@ -197,7 +197,6 @@ namespace Serein.NodeFlow.Services var context = pool.Allocate(); var instance = ioc.Get(md.ActingInstanceType); await dd.InvokeAsync(instance, [context]); - context.Reset(); pool.Free(context); } ioc.Build(); // 绑定初始化时注册的类型 @@ -225,7 +224,6 @@ namespace Serein.NodeFlow.Services var context = pool.Allocate(); var instance = ioc.Get(md.ActingInstanceType); await dd.InvokeAsync(instance, [context]); - context.Reset(); pool.Free(context); } ioc.Build(); // 绑定初始化时注册的类型 @@ -255,7 +253,6 @@ namespace Serein.NodeFlow.Services var context = pool.Allocate(); var instance = ioc.Get(md.ActingInstanceType); await dd.InvokeAsync(instance, [context]); - context.Reset(); pool.Free(context); } @@ -304,7 +301,6 @@ namespace Serein.NodeFlow.Services var token = WorkOptions.CancellationTokenSource.Token; var context = pool.Allocate(); await startNode.StartFlowAsync(context, token); - context.Reset(); pool.Free(context); return; } @@ -330,7 +326,6 @@ namespace Serein.NodeFlow.Services var result = await startNode.StartFlowAsync(context, WorkOptions.CancellationTokenSource.Token); // 开始运行时从选定节点开始运行 checkpoints["执行流程"] = sw.Elapsed; - context.Reset(); pool.Free(context); checkpoints["释放Context"] = sw.Elapsed; @@ -437,8 +432,6 @@ namespace Serein.NodeFlow.Services } finally { - - context.Reset(); pool.Free(context); } } diff --git a/Serein.Proto.WebSocket/Handle/WebSocketHandleModule.cs b/Serein.Proto.WebSocket/Handle/WebSocketHandleModule.cs index 9d6c92a..c579b2d 100644 --- a/Serein.Proto.WebSocket/Handle/WebSocketHandleModule.cs +++ b/Serein.Proto.WebSocket/Handle/WebSocketHandleModule.cs @@ -344,7 +344,7 @@ namespace Serein.Proto.WebSocket.Handle return; } // 返回结果 - var responseData = context.OnReplyMakeData(context, data); + var responseData = context.OnReplyMakeData?.Invoke(context, data); if (responseData is null) { context.TriggerExceptionTracking(new ArgumentNullException($"处理回调函数 OnReplyMakeData 返回 null")); diff --git a/Serein.Proto.WebSocket/SereinWebSocketService.cs b/Serein.Proto.WebSocket/SereinWebSocketService.cs index e433627..277ebaa 100644 --- a/Serein.Proto.WebSocket/SereinWebSocketService.cs +++ b/Serein.Proto.WebSocket/SereinWebSocketService.cs @@ -325,14 +325,22 @@ namespace Serein.Proto.WebSocket { await SocketExtension.SendAsync(webSocket, text); // 回复客户端,处理方法中入参如果需要发送消息委托,则将该回调方法作为委托参数传入 } - /* - ObjectPool contextPool = new ObjectPool(() => - { - return new WebSocketMsgContext(sendasync); - }, 20); - var context = contextPool.Allocate(); - contextPool.Free(context); - */ + + ObjectPool contextPool = new ObjectPool(() => + { + var context = new WebSocketHandleContext(sendasync); + context.OnExceptionTracking = _onExceptionTracking; + context.OnReplyMakeData = _onReplyMakeData; + context.OnReply = _onReply; + return context; + }, context => + { + context.MsgRequest = null; + context.MsgData = null; + context.ErrorMessage = null; + context.Model = null; + }); + while (webSocket.State == WebSocketState.Open) { var message = await tranTool.WaitMsgAsync(); // 有消息时通知 @@ -341,12 +349,10 @@ namespace Serein.Proto.WebSocket Console.WriteLine($"WebSocket 消息解析失败: {message}"); continue; } - var context = new WebSocketHandleContext(sendasync); + var context = contextPool.Allocate(); context.MsgRequest = jsonReques; - context.OnExceptionTracking = _onExceptionTracking; - context.OnReplyMakeData = _onReplyMakeData; - context.OnReply = _onReply; await HandleAsync(context); // 处理消息 + contextPool.Free(context); } } diff --git a/Workbench/Serein.Workbench.csproj b/Workbench/Serein.Workbench.csproj index 21e22fc..0887490 100644 --- a/Workbench/Serein.Workbench.csproj +++ b/Workbench/Serein.Workbench.csproj @@ -69,6 +69,7 @@ +