简体   繁体   English

使用IIS Express / Visual Studio进行SimpleInjector验证过程

[英]SimpleInjector Verification process with IIS Express / Visual Studio

I have a proprietary event model built into my solution that has a subscription instantiation process that uses the GetAllInstances() method of SimpleInjector to locate all of the subscribers of an event 我有一个内置于我的解决方案中的专有事件模型,它具有一个订阅实例化过程,该过程使用GetAllInstances()方法来定位事件的所有订阅者

public IEnumerable<ISubscriber<T>> GetSubscriptions<T>()
    where T : IEvent
{
    return _container.GetAllInstances<ISubscriber<T>>();
}

I am getting a massive difference in performance depending on whether I register all instances of ISubscriber or not 根据我是否注册了所有ISubscriber实例,我的性能会有很大差异

this is the code I use to register ISubscriber 这是我用来注册ISubscriber的代码

internal void Configure(Container container)
{
    container.RegisterManyForOpenGeneric(
        typeof(ISubscriber<>),
        AccessibilityOption.PublicTypesOnly,
        (serviceType, implTypes) => 
            container.RegisterAll(serviceType, implTypes),
        AppDomain.CurrentDomain.GetAssemblies()
    );

    container.RegisterDecorator(typeof(ISubscriber<>), 
        typeof(SubscriberTraceDecorator<>));

    container.RegisterDecorator(typeof(ISubscriber<>), 
        typeof(SubscriberExceptionDecorator<>));
}

When I bootstrap the container without the call to RegisterManyForOpenGeneric the container verification takes around 11 seconds and returns the results: 当我在没有调用RegisterManyForOpenGeneric的情况下引导容器时,容器验证大约需要11秒并返回结果:

Configuration Warnings: No warnings detected. 配置警告:未检测到警告。

Registrations: Count = 158 注册:计数= 158

However, when I uncomment the call to RegisterManyForOpenGeneric the container verification takes around 72 seconds and returns the results: 但是,当我取消对RegisterManyForOpenGeneric的调用时,容器验证大约需要72秒并返回结果:

Configuration Warnings: 136 container-registered types have been detected that are referenced by 181 components 配置警告:已检测到136个容器注册类型,这些类型由181个组件引用

Registrations: Count = 475 注册:计数= 475

My question is - is this ok or am I doing something wrong here? 我的问题是 - 这是好的还是我在这里做错了什么? I am adding more ISubscriber classes all the time and start up is now (way) too slow ... 我一直在添加更多的ISubscriber类,启动现在(方式)太慢了......


Update 更新

It seems this is only an issue for a WebAPI project running inside Visual Studio . 对于在Visual Studio中运行的WebAPI项目来说,这似乎只是一个问题。 Bootstrapping from a Console Application takes 15 seconds running in Visual Studio. 从控制台应用程序引导需要在Visual Studio中运行15秒。 After deploying the WebAPI project to IIS the verification takes 6 seconds. 将WebAPI项目部署到IIS后,验证需要6秒钟。

Without a call to Verify() , the Simple Injector container will fallback to a sort of 'just in time' compilation of delegates during the time they are requested for the first time. 如果没有调用Verify() ,Simple Injector容器将在第一次请求代理期间回退到一种“及时”的代理编译。 In that case the container will often build a single delegate for the creation of a whole object graph (that 'root' object + all its direct and indirect dependencies). 在这种情况下,容器通常会构建一个委托来创建整个对象图(即'root'对象及其所有直接和间接依赖关系)。 Since a delegate is built for a whole object graph there is often just a single delegate being compiled. 由于委托是为整个对象图构建的,因此通常只编译一个委托。

Compare that to calling the Container.Verify() method. 将其与调用Container.Verify()方法进行比较。 When called, this method iterates over all registrations and requests an instance for each registration. 调用时,此方法将遍历所有注册并请求每个注册的实例。 This forces the compilation of a delegate for each registration in the container (not only for the root types that are requested directly). 这会强制为容器中的每个注册编译委托(不仅针对直接请求的根类型)。

In other words, there is a lot of overhead in calling Verify and all this generation and compilation is done at the start-up phase of your application, compared to the just-in-time like behavior you'd otherwise get. 换句话说,在调用Verify会有很多开销,所有这些生成和编译都是在应用程序的启动阶段完成的,而不是像你那样得到的即时行为。

Calling Verify() during start-up is not suited for each application. 在启动期间调用Verify()不适合每个应用程序。 The time it takes for Verify() to complete depends on a lot of factors, such as: Verify()完成所需的时间取决于很多因素,例如:

  • The power of your machine. 你的机器的力量。
  • Whether you're running inside the debugger or not. 您是否在调试器内部运行。
  • The number of registrations in the container. 容器中的注册数量。
  • The use of special features. 使用特殊功能。 As you have noticed applying decorators can have impact on the compilation process. 您已经注意到应用装饰器会对编译过程产生影响。 This especially holds when a decorator contains generic type constraints. 当装饰器包含泛型类型约束时,这尤其成立。

It is good to always call Verify() during start-up, until... 最好在启动期间始终调用Verify() ,直到......

Until the configuration gets too big to call Verify() . 直到配置太大而无法调用Verify() In that case you can do the following: 在这种情况下,您可以执行以下操作:

  1. Prevent calling Verify when the debugger is attached, since the overhead is here the biggest. 阻止调用Verify何时连接调试器,因为开销在这里是最大的。
  2. Prevent calling Verify during start-up in production if it takes too long for the application to start up. 如果启动应用程序需要很长时间,请在生产启动期间阻止调用Verify
  3. Create a unit test that calls into the bootstrapper code to request a configured container instance and let the unit test call Verify() on it. 创建一个单元测试,调用bootstrapper代码来请求一个已配置的容器实例,并让单元测试对它调用Verify() This ensures that configuration errors are still caught long before rolling the software out to test, acceptance or production. 这可确保在将软件滚动到测试,验收或生产之前很长时间内仍然会发现配置错误。 A verifiable configuration is very important. 可验证的配置非常重要。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM