【发布时间】:2026-01-04 16:55:02
【问题描述】:
我担心在一个大型 .net 项目(大约有 50 万活跃用户)中使用 PostSharp 和 Spring.NET 对性能的影响。
基本上我想要这样的东西:我不想在创建用户报告时生成数百万次的日志记录。但是当用户使用系统时,我想记录他/她的一些活动。大多数 AOP 工具都没有这种灵活性。
有没有办法将方面附加到单个对象?或者在运行时打开或关闭一个方面?
【问题讨论】:
我担心在一个大型 .net 项目(大约有 50 万活跃用户)中使用 PostSharp 和 Spring.NET 对性能的影响。
基本上我想要这样的东西:我不想在创建用户报告时生成数百万次的日志记录。但是当用户使用系统时,我想记录他/她的一些活动。大多数 AOP 工具都没有这种灵活性。
有没有办法将方面附加到单个对象?或者在运行时打开或关闭一个方面?
【问题讨论】:
我对 PostSharp 和 Spring.NET 的理解是,您可以在设计时为您的类定义方面、切入点或其他任何内容。当您在打开或关闭方面,或更改切入点等方面使用类的对象时,您无能为力。
你会得到你在类设计时定义的东西。无论您使用一个对象,还是该类的一百万个对象。你应该非常小心地使用它们。否则,你可能会中枪。
您真正想要的是一个在对象级别而不是类级别处理方面的 AOP 工具。有一篇文章Add Aspects to Object Using Dynamic Decorator。
对我来说,方面是系统要求。系统要求是操作要求,最好在使用对象时在运行时在对象级别解决。
说实话,我不明白为什么大多数 AOP 工具都试图在设计时解决类级别的系统需求。这或许可以解释为什么这么多年后它们的采用率仍然如此有限。
【讨论】:
aop-logging-issues 日志记录的性能开销取决于它是如何完成的。
我想您想将日志记录建议注入您的代码。 动态 aop 只能是可能的
所以可能你需要compiletime aop。
我不知道 post-sharp 是怎么做 aop 的。使用编译时 linfu-aop,每个方法都会获得一个执行前和一个执行后,其中动态决定是否执行以及执行哪些 aop 方面。这个技巧实际上消除了对非虚拟方法的限制,使它们成为伪虚拟。
我更喜欢使用 log4.net 提供程序的手动(= non-aop-) 使用 common.logging 进行日志记录。此解决方案如果禁用日志记录,则运行时开销最小。启用/禁用日志记录可以在不重新编译的情况下选择性地完成 - 它只是一个配置文件,可能会说“使用 sql 的所有数据层活动”而不是“模块 xyz 中的 sql”。
高成本的堆栈跟踪分析(我在调试/跟踪、信息中为我登录或为我登录的类)每个类只进行一次。
禁用的日志记录可以减少到一个廉价的变量布尔评估加上一个 if。这种尺寸优化的速度可以由
logger.Debug(m => m("... costly string formatting "));
编译成类似于
的语法if (logger.IsDebugEnabled)
call anonymous method that does
the expensive string formatting
【讨论】:
PostSharp 和 Spring.NET 的性能不能一起讨论。 PostSharp 使用编译时编织,而 Spring.NET 使用运行时编织。这意味着 PostSharp 仅在编译时添加 AOP 开销,而 Spring.NET 仅在运行时添加 - 阅读一些 articles from SharpCrafters 以获得更多信息。
关于附加方面 - AOP 的关键特性之一是切入点。切入点可以被认为是选择是否为给定类型/方法等启用方面的谓词。因此,您始终可以创建类型结构和切入点以仅在系统的特定点上使用日志记录方面 - 这就是 AOP 的工作原理。
关于在运行时打开/关闭方面 - 对于编译到您的代码中的 PostSharp,我相信没有任何技巧是不可能的。对于 Spring.NET,它会更容易,但我仍然不明白为什么需要它。
【讨论】:
if 的逻辑。配置方面运行的方法有很多,我相信为所有调用打开日志记录会比基于方法的更难。
我积极致力于NConcern .NET AOP Framework,这是一个性能良好的新开源项目。此运行时 AOP 框架可以在非虚拟方法(包括静态方法)上注入代码,并且可以在运行时附加或分离。
大多数现有的 AOP 框架都基于相同的拦截技术。
这就是为什么它是一种简单的方法来总结关于运行时与编译时实现的限制和性能。
然而,这不是致命的,AOP 框架可以使用专有的注入技术和现代消费者 API 来实现,非常易于使用和高效。
我的实现在运行时工作,并且只有很少的限制,保持非常低的耦合并提供内置表达式树来定义建议,以通过避免反射开销来保持最佳性能。
请看一下,我对您对这个主题的看法很感兴趣。它可以帮助我改进产品。
【讨论】: