ASP.NET Web Api 2 / EF6 首次调用初始化性能

Posted

技术标签:

【中文标题】ASP.NET Web Api 2 / EF6 首次调用初始化性能【英文标题】:ASP.NET Web Api 2 / EF6 first call initialization performance 【发布时间】:2014-10-02 12:36:32 【问题描述】:

第一次调用我们的 API 总是非常慢。例如,下面演示了第一次调用完成所用的 CPU 使用率和时间:

第一次调用最多可能需要 30 秒,并且占用几乎 100% 的 CPU。调用 2 和 3 需要 200 毫秒(应该如此)。回收应用程序池后,它会和第一次调用一样。

我已经阅读了一些关于 IIS“预热”的内容并做了以下操作,但没有任何改变:

IIS 8 Application Initialization 已安装:

我在 IIS 中有以下设置:

启动模式设置为AlwaysRunning

回收超时设置为0:

空闲超时 设置为 0:

在网站上将 Preload Enabled 设置为 true:

我实际上是在RoleEntryPoint.OnStart() 的代码中设置这些。

using (var serverManager = new ServerManager())

    serverManager.ApplicationPoolDefaults.ProcessModel.IdleTimeout = TimeSpan.Zero;

    foreach (var application in serverManager.Sites.SelectMany(x => x.Applications))
    
        application["preloadEnabled"] = true;

    

    foreach (var applicationPool in serverManager.ApplicationPools)
    
        applicationPool.AutoStart = true;
        applicationPool["startMode"] = "AlwaysRunning";
        applicationPool.ProcessModel.IdleTimeout = TimeSpan.Zero;
        applicationPool.Recycling.PeriodicRestart.Time = TimeSpan.Zero;

    

    serverManager.CommitChanges();

我几乎可以肯定 Entity Framework 可能是罪魁祸首:

我们在 EDMX 模型“设计器”中从大约 100 个表生成模型。

我们正在生成由 EF Power Tools 生成的预编译视图

以下初始化正在Application_Start()中运行:

using (var context = new MyContext())

    context.Database.Initialize(false);

我在调试时没有这些“初始化”问题。

正在使用以下技术:

.NET 4.5.1 ASP.NET Web API 2 实体框架 6.1.1 IIS 8(Azure Web 角色) Unity 3.5

谁能给我其他的想法或建议?

【问题讨论】:

您是否在 applicationHost.config 文件中为 Web 应用程序设置了 preloadEnabled="true" @afrazier:是的,启动代码设置为 true。 你注释掉EF初始化代码看是否会出现秒杀? 请将设置添加到 .config 文件中,而不是通过代码进行设置。要通过代码设置它们,您需要运行应用程序。你宁愿从一开始就让它们具有正确的设置。附加说明:您是否尝试过记录分层的不同步骤,以便在服务器重新启动时运行它们? @davenewza 您的代码应该这样做。当您调用Initialize 时,将执行数据库初始化和播种。但是没有文档保证模型(视图)被加载到内存中。也许(我只是假设)模型在需要时才加载。因此,您还可以在 DB 初始化程序中运行一个简单的查询来确保发生这种情况。 【参考方案1】:

不确定是否有人解决了这个问题,但我了解到 Entity Framework 初始启动时出现的一些性能问题。 Julie Lerman 在她关于实体框架的 Pluralsight 课程中讨论了这一点,并且在以下来自 Microsoft 的文章摘录中也提到了这一点:

对性能的最大拖累之一是在应用程序进程中首次使用上下文所涉及的启动时间。不过,您可以做很多事情来改善启动时间。希望您已经从我自己的文章或其他资源中学到了这些技巧,例如 bit.ly/3D6AiC 上有关性能考虑的 MSDN 文档。

通常会影响性能的启动步骤是映射视图的视图生成,其中 EF 创建相关 SQL 以查询模型中的每个实体集。这些视图在您的应用程序运行时得到利用,因此对于某些查询,EF 不必即时计算 SQL。无论您是使用 EF 设计器还是使用 Code First 创建模型,都会生成视图。您可以预先生成这些视图并将它们编译到应用程序中以节省时间。 http://msdn.microsoft.com/en-us/magazine/dn532202.aspx

在这里,她似乎不仅仅是在谈论“初始加载”,而是在谈论上下文的实际首次使用。我想快速搜索 Julie Lerman 和实体框架性能问题。在对我的 Web API 进行初始调用时,我注意到类似的缓慢。第一个之后的每个呼叫都明显更快。我个人还没有发现它太糟糕了,所以我忽略了它(现在)。但是我确实发现它在调试模式下不会发生很有趣。抱歉,如果您已经探索过这些选项,但我希望这会有所帮助。

【讨论】:

以上是关于ASP.NET Web Api 2 / EF6 首次调用初始化性能的主要内容,如果未能解决你的问题,请参考以下文章

在 HTTPS 上使用 Windows 身份验证首次调用 ASP.NET Core 2.0 Web API 在 Chrome 中总是失败

在 asp.net MVC5 EF6 中使用流利的 api 映射表?

用 Visual Studio 和 ASP.NET Core MVC 创建首个 Web API

第二章 指南用 Visual Studio 和 ASP.NET Core MVC 创建首个 Web API

ASP.NET Core设置Web API 响应的数据格式——Produces 特性篇

Asp.Net Web API 2第五课——Web API路由