动态代理生成速度

发布于 2024-12-03 01:00:08 字数 1145 浏览 3 评论 0原文

我正在尝试解决一些启动时间问题。经过一些分析后,我发现罪魁祸首是 ClassProxyGenerator.GenerateCode。每种类型第一次需要 400-600 毫秒。因此,如果应用程序的入口点有 8 个依赖项(在链中)需要生成代理,则应用程序的启动时间将增加 4.8 秒。这可能看起来不是很多,但对于用户来说,却像是很长一段时间。

有什么改进建议吗?

更新:

我可以使用以下控制台应用程序重现时间:

        var container = new WindsorContainer();
        container.Register(Component.For<Interceptor>()); // dummy IInterceptor...does nothing
        container.Register(Component.For<IMyRepository, MyAbstractRepository>().Interceptors<Interceptor>());
        var t = DateTime.Now;
        var instance = container.Resolve<IMyRepository>();
        Debug.WriteLine("Resolved in " + (DateTime.Now - t).TotalMilliseconds);

输出介于 550 毫秒和 750 毫秒之间。

IMyRepository 是 30 种实体类型(由 T4 模板生成)的存储库接口。它有 31 个 IQueryable、31 个 Save 重载和 31 个 Delete 重载。 MyAbstractRepository 是一个部分抽象类。它声明了相同的 3 x 31 方法。

如果我删除所有保存和删除方法并仅保留 31 个 IQueryables 并且不注册抽象存储库,

  container.Register(Component.For<IMyRepository>().Interceptors<Interceptor>());

那么初始生成仍需要大约 250 毫秒的时间。

这是一台非常(非常非常)快的机器……所以现实世界中的任何东西都可能比上面列出的数字慢。

I'm trying to troubleshoot some startup time concerns. After doing some profiling, I've found the main culprit is ClassProxyGenerator.GenerateCode. This takes 400-600ms per type the first time. So if the entry point to the application has 8 dependencies (in a chain) which need proxies generated, the startup time of the application goes up by 4.8 seconds. This might not seem like a lot, but to a user, it seems like ages.

Any advice for improving this?

Update:

I can reproduce the time with the following console application:

        var container = new WindsorContainer();
        container.Register(Component.For<Interceptor>()); // dummy IInterceptor...does nothing
        container.Register(Component.For<IMyRepository, MyAbstractRepository>().Interceptors<Interceptor>());
        var t = DateTime.Now;
        var instance = container.Resolve<IMyRepository>();
        Debug.WriteLine("Resolved in " + (DateTime.Now - t).TotalMilliseconds);

Outputs somewhere between 550ms and 750ms.

IMyRepository is a repository interface for 30 entity types (generated by a T4 template). It has 31 IQueryables, 31 Save overloads, and 31 Delete overloads. MyAbstractRepository is a partial abstract class. It declares the same 3 x 31 methods.

If I remove all the save and delete methods and leave just the 31 IQueryables AND don't register the abstract repository

  container.Register(Component.For<IMyRepository>().Interceptors<Interceptor>());

I still run around 250ms for the initial generation.

This is a very (very very) fast machine...so anything in the real world will likely perform slower than the numbers listed above.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

青衫负雪 2024-12-10 01:00:08

您也许能够在不同的线程中执行代理初始化,以便应用程序本身可以在生成代理时继续初始化。考虑将其排队到线程池中。

另一种选择可能是将代理编译成持久的程序集文件,然后将其保存到磁盘。这样做将显着缩短首次运行后的启动时间。

我不知道为什么 Castle 的动态代理需要这么长时间才能初始化。我不使用它们,我通常直接发出代码(作为简单方法的 LCG,以及通过完整的 Reflection.Emit 来实现完整的实现)。即使生成数百个 LCG 方法,我也从未遇到过这么长时间的延迟。也许使用不同的方法/库(LinFu 等)也可以解决这个问题。

You might be able to perform the proxy initialization in a different thread, so that the application itself can continue to initialize while the proxies are generated. Consider queuing this into the threadpool.

Another option might be to compile the proxies into a persisted assembly file, which is then saved to disk. Doing this would significantly lower the startup time after the first run.

I'm not sure why Castle's dynamic proxies take so long to initialize. I don't use them, I usually emit code directly (either as LCG for simple methods, and via full Reflection.Emit for complete implementations). I never had such long delays, even when generating hundreds of LCG methods. Maybe using a different approach/library (LinFu etc.) might fix the issue as well.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文