预编译视图的首次访问速度慢

Posted

技术标签:

【中文标题】预编译视图的首次访问速度慢【英文标题】:Slow first visit on precompiled view 【发布时间】:2018-06-08 12:28:33 【问题描述】:

我已经预编译了我的应用程序: precompilation settings,也将编译配置设置为

<compilation targetFramework="4.6.2"
             batch="false"
             debug="false"
             optimizeCompilations="true">
</compilation>

但是在每次第一次访问页面时仍然需要很长时间(不仅是对应用程序的第一次请求,这可以通过应用程序初始化来解释,而且对每个视图的第一次请求,即使在应用程序初始化之后也是如此)。

我使用分析器来检查它是否是我们的代码,但它执行得很快。第一次访问页面会有大约 20 秒的延迟(有时甚至长达 60 秒)。 Profiler 显示了这一点(对第一页访问的响应延迟返回),即使视图是预编译的(注意最后一次 SQL 查询和响应后的 20 秒延迟): profiler result on first request.

每个下一页请求的响应都会立即返回: profiler result on second request.

我检查了 ORM 初始化,尝试缩小 js/css,压缩它们并检查所有其他已知选项,但无济于事。即使应用程序和应用程序池已预热,第一次请求时的每个视图/页面都返回缓慢。

然后我在 IIS 中启用了跟踪并发现以下内容: delay after HANDLER_CHANGED event

处理程序更改后发生延迟。现在......奇怪的是,我猜它正在从为 null 的 OldHandlerName 更改。这可能是原因吗?或者可能是延迟后发生的事件(HttpCacheModule)?我发现了其他几个类似的发现,这些发现与此处的初始页面请求速度慢有关,但没有一个得到正确回答。可以找到其中一个答案 here,但更改 outputCache 并没有帮助。我的 outputCache 设置:

<caching>
    <outputCacheSettings>
         <!--outputCacheSettings - Controls how controller actions cache content in one central location.
                           You can also modify the web configuration file without recompiling your application.--> 
        <outputCacheProfiles>
             <!--Cache the 400 Bad Request route for a day.--> 
            <add name="BadRequest" duration="86400" location="Server" varyByParam="none" />
             <!--Cache the 403 Forbidden route for a day.--> 
            <add name="Forbidden" duration="86400" location="Server" varyByParam="none" />
             <!--Cache the 405 Method Not Allowed route for a day.--> 
            <add name="MethodNotAllowed" duration="86400" location="Server" varyByParam="none" />
             <!--Cache the 404 Not Found route for a day.--> 
            <add name="NotFound" duration="86400" location="Server" varyByParam="none" />
             <!--Cache the 401 Unauthorized route for a day.--> 
            <add name="Unauthorized" duration="86400" location="Server" varyByParam="none" />
             <!--Cache the 500 Internal Server Error route for a day.--> 
            <add name="InternalServerError" duration="86400" location="Server" varyByParam="none" />
        </outputCacheProfiles>
    </outputCacheSettings>
</caching>

我在这里碰壁了……有什么想法吗?

:编辑: 进一步分析后发现,即使在运行预编译后,

C:\Windows\Microsoft.NET\Framework64\v4.0.30319\Temporary ASP.NET Files 

在部署时未填充 dll。当我跑步时

aspnet_compiler -v /virtual_path

实际上它确实将所有页面预编译到该临时文件夹,但是当我第一次访问页面时,会创建该 .dll 的第二个浅表副本,这会导致延迟。在该文件由 IIS 而不是预编译工具创建后,视图工作正常。

所以...看起来 IIS 不知道这些 dll 已经预编译并准备好执行操作。你知道如何让它为人所知吗?我们甚至可以完全禁用 Temporary ASP.NET Files 并强制它只使用我们应用程序的 bin 文件夹吗?

:EDIT2: 我看到 IIS 页面和控件中有一个选项,称为编译模式,默认情况下它是“始终”(这意味着它无论如何都会强制编译),但正如 msdn 中所述,这些设置适用于 ASP仅限 .NET 网络表单。 MVC 必须有类似的设置。帮助! :-)

【问题讨论】:

【参考方案1】:

预编译并不能满足您的所有想法。它确实会编译成 dll,但随后需要将该 dll 从 IL 转换为机器代码。当您在 IIS 中启动应用程序时会发生这种情况。如果您使用的是 WIndows Server 2012 或更高版本,您可以在应用程序池中设置一些功能,以帮助它在使用 Always Running 启动模式加载后保持热状态。

您可以通过打开 IIS 管理器找到此设置 |应用程序池 |选择合适的应用程序池 |高级设置并将启动模式设置为始终运行。

初始命中仍需要一些编译时间,但此后应用程序应保持加载状态,并且仅在应用程序池被强制回收时才被拆除。

【讨论】:

应用程序池已设置为始终运行,应用程序预加载已启用,appInitialization 也已启用。如果只有对应用程序的第一个请求很慢,这可能是一个解决方案,但我们正在讨论每页的每个第一个请求,即使在应用程序已正确初始化之后也是如此。所以我们有第 1 页、第 2 页、第 3 页。我们点击了 Page1(假设我们没有自动启动应用程序池,因此正在初始化应用程序,然后呈现视图),但是当我们点击 Page2 和 Page3 时,第一次点击它们时也会发生延迟。 这是定义为 Web 应用程序项目还是网站项目? 它是 ASP.NET MVC Web 应用程序,托管在 IIS 的默认网站下。 这很不寻常。视图中是否有内联的 C# Razor 函数? 不,视图中只使用了 DevExpress 控件,没有 C# Razor 函数。

以上是关于预编译视图的首次访问速度慢的主要内容,如果未能解决你的问题,请参考以下文章

IIS预编译提升加载速度

如何调试速度慢得无法忍受的 Rails 资产预编译

怎么让IIS7第一次访问相应速度加快

vue--按需加载的3种方式(解决网页首次加载速度慢的问题)

优化vue项目的首屏加载速度

php+mssql 访问速度慢是啥原因?