如何“热身”entity framework? 什么时候变“冷”?

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

前言:

最近我对Entity Framework进行了大量的研究,并且一直困扰着我的是当查询没有被加热时的性能,所谓的冷查询。

我浏览了Entity Framework 5.0的性能考虑文章。 作者介绍了冷热查询的概念,以及它们如何不同,我也注意到自己不知道它们的存在。 这里值得一提的是我背后只有六个月的经验。

现在我知道我还可以研究哪些主题,如果我想更好地了解性能方面的框架。 不幸的是,互联网上的大部分信息都是过时的或主观性的膨胀,因此我无法find任何关于暖和 查询主题的附加信息。

基本上我到目前为止注意到的是,每当我必须重新编译或回收命中,我最初的查询变得非常缓慢。 如预期的那样,随后的数据读取是快速的( 主观的 )。

我们将迁移到Windows Server 2012,IIS8和SQL Server 2012,作为初级,我实际上赢得了自己的机会,在其他之前testing它们。 我很高兴他们介绍了一个预热模块,可以让我的应用程序为第一个请求做好准备。 但是,我不知道如何继续预热我的entity framework。

我已经知道的是值得的:

  • build议提前生成我的意见。
  • 最终将我的模型转换为单独的程序集。

我认为,按照常识走, 可能是错误的做法

  • 在“应用程序启动”中执行虚拟数据读取,以便加热,生成和validation模型。

问题:

  • 随时在我的entity framework上获得高可用性的最佳方法是什么?
  • entity framework在什么情况下再次变得“冷”? (重新编译,回收,IIS重新启动等)
  • 随时在我的entity framework上获得高可用性的最佳方法是什么?

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

静态CompiledQuerys是很好的,因为它们很容易编写,并有助于降低性能。 但是,使用EF5,不需要编译所有查询,因为EF本身会自动编译查询。 唯一的问题是,当caching被扫描时,这些查询可能会丢失。 因此,您仍然希望持有对那些仅发生非常罕见的编译查询的引用,但这些代码很贵。 如果你把这些查询放到静态类中,它们将在第一次被需要的时候被编译。 对于某些查询来说这可能已经太迟了,所以您可能需要在应用程序启动时强制编译这些查询。

如您所提,预生成视图是另一种可能性。 特别是那些需要很长时间才能编译而且不会改变的查询。 这样,您可以将运行时的性能开销移至编译时间。 这也不会引入任何滞后。 但是,当然这个改变会传递到数据库,所以处理起来并不容易。 代码更加灵活。

不要使用大量的TPTinheritance(这是EF中的一般性能问题)。 不要把你的inheritance层次太深也不要太宽。 只有2-3个特定于某个类的属性可能不足以要求自己的types,但可以作为可选(可空)属性处理为现有types。

不要长期坚持单一的背景。 每个上下文实例都有自己的第一级caching,随着性能的增长,性能下降。 上下文创build是便宜的,但是上下文的caching实体内部的状态pipe理可能变得昂贵。 其他caching(查询计划和元数据)在上下文之间共享,并与AppDomain一起死亡。

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

  • entity framework在什么情况下再次变得“冷”? (重新编译,回收,IIS重新启动等)

基本上,每当你失去你的AppDomain。 IIS每29个小时执行一次重新启动,所以你永远不能保证你会有你的实例。 也经过一段时间没有活动的AppDomain也closures。 你应该尝试再次快速上来。 也许你可以做一些asynchronous初始化(但要小心multithreading问题)。 在没有任何请求阻止AppDomain死亡的时候,您可以使用在应用程序中调用虚拟页面的计划任务,但最终会这样。

我也假定当你改变你的configuration文件或更改程序集时,将会重新启动。

如果您正在寻找所有通话的最佳性能,则应仔细考虑您的架构。 例如,当应用程序加载而不是在每个请求上使用数据库调用时,预先在服务器RAM中预先caching经常使用的查找是有意义的。 这种技术将确保常用数据的最小应用响应时间。 但是,必须确保具有良好行为的到期策略,或者每当进行影响caching数据的更改时总是清除caching,以避免并发问题。

一般来说,当本地caching的信息过时或需要事务处理时,您应该努力devise分布式体系结构以仅需要基于IO的数据请求。 在内存caching检索中,任何“通过线路”数据请求的检索时间通常比本地检索时间长10-1000倍。 与“本地与远程”数据问题相比,仅仅这一个事实经常使“冷数据与温数据”的讨论变得无足轻重。

一般提示。

  • 执行严格的日志logging,包括访问请求时间
  • 在初始化应用程序时执行虚拟请求,以温和引导从上一步中拾取的非常慢的请求。
  • 除非是真正的问题,否则不要打扰优化,与应用程序的消费者沟通并询问。 如果仅仅是找出需要优化的东西,那么就可以有一个连续的反馈循环。

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

  • 复杂性较低 – 无论框架发生什么变化,您都在以一种可行的方式预热应用程序,并且您不需要找出可能的时髦API /框架内部以正确的方式进行操作
  • 更广泛的覆盖范围 – 您正在与缓慢请求相关的所有caching层次变暖。

解释caching何时变得“冷”。

这发生在您的框架中的任何一个应用caching的 上,在性能页面的顶部有一个很好的描述。

  • 当一个caching需要在caching失效后进行validation时,这可能是一个超时或者更为智能的(即,caching项目发生变化)。
  • 当caching项目被驱逐时,执行此操作的algorithm在您链接的性能文章的 “caching驱逐algorithm”一节中进行了描述,但总之如此。
    • LFRU(最不频繁 – 最近使用)caching命中次数和年龄限制800个项目。

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

正如你所说,使用“预先生成的视图”,这是你所需要做的。

从链接中提取:“当生成视图时,也会对其进行validation。从性能angular度来看,视图生成的绝大部分成本实际上是对视图的validation”

这意味着性能敲门声将发生在您build立模型组件时。 您的上下文对象然后将跳过“冷查询”并保持对上下文对象生命周期的持续时间以及随后的新的对象上下文的响应。

执行不相关的查询将除了消耗系统资源之外别无它用。

快捷方式…

  1. 跳过预先生成的视图的所有额外工作
  2. 创build你的对象上下文
  3. 消除这个甜蜜的不相关的查询
  4. 然后在整个过程中只保留一个对象上下文的引用(不推荐)。

我没有这个框架的经验。 但是在其他上下文中,例如Solr,除非可以caching整个数据库(或索引),否则完全虚拟读取将不会有多大用处。

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