简体   繁体   English

Petapoco存储库模式存在重大性能问题

[英]Petapoco repository pattern significant performance issues

We are using the petapoco repository pattern (similar to this blog post ). 我们正在使用petapoco存储库模式(类似于此博客文章 )。 As the page loads we open up the repository, run the query, dispose and then carry on processing. 在页面加载时,我们打开存储库,运行查询,配置然后进行处理。 This is fine on light pages, but when this happens a few times in the page we get quite significant performance degradation. 在浅色页面上这很好,但是在页面上多次发生这种情况时,性能会大大下降。

I had, perhaps wrongly, assumed that connection pooling would cope with this, which is enabled. 我可能错误地假设连接池可以解决此问题,该功能已启用。

I ran a couple of tests. 我进行了几次测试。

The page it's on (it's an aspx page) takes around 1.2 seconds to load as it is at the moment. 该页面所在的页面(这是一个aspx页面)目前需要大约1.2秒的时间来加载。 The page is running around 30 database queries...and, looking at the profiler, is doing a login and logout per query (even with connection pooling). 该页面运行着大约30个数据库查询...,并查看分析器,正在对每个查询进行登录和注销(即使使用连接池)。

If I persist the connection and don't close until the page ends, this drops to around 70ms, which is quite a significant saving. 如果我坚持连接并且直到页面结束都没有关闭,这会减少到70毫秒左右,这是一笔可观的节省。

Perhaps we need to keep the Database object hanging around for the request, but I didn't think PetaPoco had this much of an overhead...particularly with the connection pooling. 也许我们需要为请求保留数据库对象,但是我不认为PetaPoco有这么多的开销……特别是在连接池方面。

I have created a test app to demonstrate it. 我创建了一个测试应用程序来演示它。

This demonstrates that loading a user 1000 times takes 230ms if the repository is reused, but takes 3.5seconds if the repository is recreated every time. 这表明,如果重新使用存储库,则加载1000次用户需要230毫秒,而如果每次都重新创建存储库则需要3.5秒。

Your usage of connection pooling is breaking best practices. 您对连接池的使用正在打破最佳实践。

It says nowhere to get rid of it after every statement. 它说在每句话之后都无处可除。 I normally keep a connection / repository around while doing processing and only close it when my function is finished (with MVC). 我通常在进行处理时保持连接/存储库的状态,并且仅在功能完成时(使用MVC)关闭它。

Yes, even the connection pool has overhead and you seem to be really bound on making that show. 是的,即使连接池也有开销,并且您似乎确实必须要进行演出。

What I always do is create a single instance of my repository per request. 我总是做的是为每个请求创建一个存储库实例。 Because I develop almost exclusively using the MVC pattern, that means I create a private class level variable in each of my controllers and use it to service any requests within my Action methods. 因为我几乎都是使用MVC模式进行开发的,所以这意味着我在每个控制器中创建了一个私有类级别的变量,并使用它来为Action方法中的所有请求提供服务。 Translated to WebForms (ASPX), that means I would create one in the BeforeLoad (or whatever the event just before PageLoad is) and pass it around as needed. 转换为WebForms(ASPX),这意味着我将在BeforeLoad(或PageLoad之前的任何事件)中创建一个,并根据需要传递它。 I don't think keeping a class-level instance is a good idea for Webforms though, but I can't remember enough to be sure. 我认为保留类级实例对于Webforms来说不是一个好主意,但是我记不清足够多的把握。

The rule of thumb is to use one instance of your repo (or any other type of class really) for the entirety of your request, which is usually a page load or Ajax call. 经验法则是在整个请求中使用仓库的一个实例(或者实际上是其他任何类型的类),通常是页面加载或Ajax调用。 And for the reasons you've pointed out. 并且出于您已指出的原因。

Remember: information on the internet is free, and you get what you pay for. 请记住:互联网上的信息是免费的,您将获得所需的费用。

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

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