How to "warm-up" Entity Framework? When does it get "cold"?

不,我第二个问题的答案不是冬天。

前言:

我最近对实体框架做了很多研究,有一件事一直困扰着我,那就是当查询没有预热时,它的性能,也就是所谓的冷查询。

我浏览了实体框架5.0的 性能考虑因素文章。作者介绍了 Warm查询的概念以及它们的区别,我也注意到了自己并不知道它们的存在。这里值得一提的是,我只有六个月的背后经验。

现在我知道了如果我想更好地理解框架的性能,我还可以研究哪些主题。不幸的是,互联网上的大多数信息已经过时或者因为主观性而臃肿,因此我无法找到关于 温暖查询主题的任何其他信息。

基本上,到目前为止我注意到的是,每当我必须重新编译或者回收时,我的初始查询都变得非常慢。正如预期的那样,任何后续数据读取都是快速的(很主观)。

我们将迁移到 WindowsServer2012、 IIS8和 SQLServer2012,作为一名初级学员,我实际上赢得了在其他人之前测试它们的机会。我很高兴他们引入了一个预热模块,这将使我的应用程序为第一个请求做好准备。但是,我不确定如何继续预热我的实体框架。

我已经知道的事情是值得去做的:

  • 按建议预先提出我的意见。
  • Eventually move my models into a separate assembly.

What I consider doing, by going with common sense, 可能是错误的方法:

  • 在应用程序启动时执行虚拟数据读取,以便加热数据 生成并验证模型。

问题:

  • 什么是最好的方法可以在任何时候在我的实体框架上建立高可用性?
  • 在什么情况下实体框架会再次“冷”? (重新编译、回收、 IIS 重新启动等)
27588 次浏览

正如您所说的,使用“预生成视图”,这就是您真正需要做的全部事情。

摘自你的 链接: ”当视图生成时,它们也会被验证。从性能的角度来看,视图生成的绝大部分成本实际上是视图的验证

这意味着在构建模型组装时将发生性能冲击。然后,上下文对象将跳过“冷查询”,并在上下文对象生命周期以及随后的新对象上下文中保持响应。

执行不相关的查询只会消耗系统资源。

捷径..。

  1. 跳过所有预生成视图的额外工作
  2. 创建对象上下文
  3. 开始甜蜜的无关问题
  4. 然后在流程的持续时间内保留对对象上下文的引用 (不推荐)。

我在这方面没有经验。但是在其他上下文中,例如 Solr,除非能够缓存整个 DB (或索引) ,否则完全虚拟的读操作将没有多大用处。

更好的方法是记录查询,从日志中提取最常见的查询,并使用它们进行预热。只是确保在继续之前不要记录预热查询或从日志中删除它们。

如果您正在寻找所有调用的最大性能,那么您应该仔细考虑您的体系结构。例如,当应用程序加载时,在服务器 RAM 中预缓存经常使用的查找,而不是对每个请求使用数据库调用,这可能是有意义的。这种技术将确保常用数据的最短应用程序响应时间。但是,必须确保具有行为良好的过期策略,或者在进行影响缓存数据的更改时始终清除缓存,以避免并发性问题。

In general, you should strive to design distributed architectures to only require IO based data requests when the locally cached information becomes stale, or needs to be transactional. Any "over the wire" data request will normally take 10-1000 times longer to retrieve than an a local, in memory cache retrieval. This one fact alone often makes discussions about "cold vs. warm data" inconsequential in comparison to the "local vs. remote" data issue.

  • 什么是最好的方法可以在任何时候在我的实体框架上建立高可用性?

您可以混合使用预生成视图和静态编译查询。

静态 已编译的查询是很好的,因为它们快速、易于编写,有助于提高性能。但是对于 EF5,不需要编译所有查询,因为 EF 会自动编译查询。唯一的问题是,当缓存被清除时,这些查询可能会丢失。因此,对于那些非常罕见但代价高昂的查询,您仍然希望保留对自己编译查询的引用。如果您将这些查询放入静态类中,它们将在第一次需要时被编译。这对于某些查询来说可能太晚了,因此您可能希望在应用程序启动期间强制编译这些查询。

Pregenerating views is the other possibility as you mention. Especially, for those queries that take very long to compile and that don't change. That way you move the performance overhead from runtime to compile time. Also this won't introduce any lag. But of course this change goes through to the database, so it's not so easy to deal with. Code is more flexible.

不要使用大量的 TPT 继承(这是 EF 中的一般性能问题)。不要构建太深或太宽的继承层次结构。只有特定于某些类的2-3个属性可能不足以要求一个自己的类型,但可以作为现有类型的可选(可空)属性进行处理。

不要长时间拘泥于一个单一的背景。每个上下文实例都有自己的第一级缓存,这会随着缓存的增大而降低性能。上下文创建成本很低,但是上下文的缓存实体中的状态管理可能会变得昂贵。其他缓存(查询计划和元数据)在上下文之间共享,并将与 AppDomain 一起消失。

总而言之,你应该确保频繁地分配上下文,并且只在短时间内使用它们,你可以快速启动你的应用程序,你可以编译很少使用的查询,并为性能关键且经常使用的查询提供预生成的视图。

  • 在什么情况下实体框架会再次“冷”? (重新编译、回收、 IIS 重新启动等)

基本上,每次你丢失你的应用程序域名。IIS 每次重新启动 29小时,所以您永远不能保证您的实例在附近。在一段时间没有活动之后,AppDomain 也被关闭。你应该试着再快点爬上来。也许您可以异步地进行一些初始化(但是要注意多线程问题)。您可以使用预定的任务,在没有请求防止 AppDomain 死亡的时候调用应用程序中的虚拟页面,但是它最终会死亡。

我还假设,当您更改配置文件或更改程序集时,将重新启动程序。

一般提示。

  • 执行严格的日志记录,包括 访问的内容请求时间
  • Perform dummy requests when initializing your application to warm boot 非常慢 requests that you pick up from the previous step.
  • 除非是真正的问题,否则不要费心进行优化,与应用程序的使用者进行沟通并提出要求。如果只是为了计算出 需要优化的东西,那么让持续的反馈回路变得舒适。

现在来解释为什么虚拟请求不是 错误的方法

  • Less Complexity - You are warming up the application in a manner that will work regardless of changes in the framework, and you don't need to figure out possibly funky APIs/framework internals to do it 正确的方式.
  • 更大的覆盖范围 -与缓慢请求相关的所有缓存层同时进行预热。

解释什么时候缓存变冷。

这发生在应用缓存的 框架中的任何一层上,在 表演页面的顶部上有一个很好的描述。

  • When ever a cache has to be validated after a potential change that makes the cache stale, this could be a timeout or more intelligent (i.e. change in the cached item).
  • 当清除缓存项时,执行此操作的算法在 你链接的表演文章的“缓存清除算法”一节中进行了描述,但是简而言之。
    • LFRU (Least frequently - recently used) cache on hit count and age with a limit of 800 items.

您提到的其他事情,特别是重新编译和重新启动 IIS,将清除部分或全部内存缓存。