Singleton
实例是否能够提高性能而不是注册Transient
实例?据我所思,对于
Singleton
实例,仅需要一次创建新对象和相关的对象。对于Transient
实例,这个过程将在每个服务请求中重复进行。因此Singleton
似乎更好。但是使用Singleton
相比Transient
能够获得多少性能提升呢?预先感谢您的回答!
Singleton
实例是否能够提高性能而不是注册Transient
实例?Singleton
实例,仅需要一次创建新对象和相关的对象。对于Transient
实例,这个过程将在每个服务请求中重复进行。因此Singleton
似乎更好。但是使用Singleton
相比Transient
能够获得多少性能提升呢?和其他人所说的一样,性能不应该是你做决定的考虑因素:无论哪种方式,性能都不会受到明显的影响。你需要考虑的是依赖项,包括托管和非托管的依赖项。当你使用有限的资源(例如套接字和连接)时,单例是最好的选择。如果每次注入服务(瞬态)时都需要创建一个新的套接字,那么你很快就会用完套接字,然后性能就真的会受到影响。
瞬态作用域更适合临时使用和对资源影响最小的情况。例如,如果你只是进行计算,可以使用瞬态作用域,因为通过多个副本来实现不会耗尽任何资源。
当状态非常重要时,也要使用单例作用域。如果某些东西需要在一个特定操作之后持久存在,那么瞬态作用域将无法工作,因为你将没有状态,因为每次注入时它都会从头开始。例如,如果你想协调并发队列,并使用信号量进行锁定,则肯定需要一个单例作用域的服务。如果状态并不重要,则瞬态可能是更好的作用域。
最后,您必须查看您的服务对其他服务的依赖情况。如果您需要访问范围限定的服务(例如请求范围内的服务),那么单例模式不适用。虽然您可能可以使用服务定位器模式来访问这些作用域服务,但这是一个错误,并且不被推荐。基本上,如果您的服务除了其他单例服务外使用了任何东西,则应该将其视为作用域或瞬态。
长话短说,除非您有充分明确的理由将其设置为单例,否则请使用瞬态范围。这样的理由包括维护状态、高效利用有限资源等等。如果服务可以在瞬态范围中工作,并且没有更好的理由,请使用瞬态范围。
现在,ASP.NET Core的DI具有“瞬态”和“作用域”生命周期。这两者都是“瞬态”的,也就是说它们会出现并消失,但“作用域”每次创建一个“作用域”(通常是一个请求)时都会实例化一次,而“瞬态”则每次注入时总是被实例化。在这里,除非您有充分明确的理由使用“瞬态”,否则请使用“作用域”。
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
。总之:检查文档(或StackOverflow)以获取您未编写的任何服务的正确生命周期! - Jpsy我知道这里的性能不是您在寻找的,但出于好奇,我制作了一个样本基准应用程序来评估 AddSingleton 和 AddTransient 之间的差异,使用 BenchmarkDotNet。
我使用的解决方案可以在此处找到(请随意改进):https://github.com/iheb719/BenchmarkDifferentServicesInstances
这是我的总结:
我的笔记本电脑规格: BenchmarkDotNet=v0.13.1,OS=Windows 10.0.19042.1415(20H2 / October2020Update) Intel Core i7-9750H CPU 2.60GHz,1个CPU,12个逻辑核心和6个物理核心 .NET SDK=6.0.101 [Host]: .NET 6.0.1(6.0.121.56705),X64 RyuJIT DefaultJob:.NET 6.0.1(6.0.121.56705),X64 RyuJIT
我的结果:
方法 | 平均值 | 误差 | 标准差 |
---|---|---|---|
CallSingletonApp | 101.0 微秒 | 0.64 微秒 | 0.53 微秒 |
CallTransientApp | 108.3 微秒 | 1.16 微秒 | 1.03 微秒 |
因此,如果构造函数内没有大量处理,AddSingleton和AddTransient之间没有显着的差异
如回复中所提到的,这并不是关于性能的问题。
更多细节请参见下面的链接,其中非常详细地解释了差异。 AddTransient、AddScoped和AddSingleton服务的区别
唯一会影响性能的方式是如果您的构造函数做了很多事情。然而,在所有情况下都应该避免这种情况。