【问题标题】:First request slow when importing Razor views from class library in ASP.NET Core 2.1从 ASP.NET Core 2.1 中的类库导入 Razor 视图时第一次请求很慢
【发布时间】:2019-10-04 17:33:24
【问题描述】:

在 ASP.NET Core 2.1 中,我有一个带有 Razor 视图的 DLL 项目 (Microsoft.NET.Sdk),用于与多个应用程序共享常见的局部视图,如导航、页脚等。它的创建类似于described here。所以我有一个包含这些库并嵌入部分视图的 ASP.NET Core 2.1 MVC 应用程序。

虽然这可行,但我注意到此应用程序的首页加载时间大幅增加。主 HTML 文档大约需要 3 秒。随后的请求非常快(~30-40ms)。我尝试删除共享 DLL 嵌入的应用程序中的所有部分视图。现在第一个请求要快得多(大约 300 毫秒)。

所以它似乎是由从共享 DLL 项目加载 Razor 视图引起的。我尝试在 AppStartup 方法中使用不同的方法预加载程序集(灵感来自this question):

GC.KeepAlive(typeof(Assets.AssetStartup));
System.Reflection.Assembly.Load("Assets"); 

性能没有太大差异,第一次请求仍然需要大约 2.9 秒。

我该如何改进?

我知道 EntityFramework 的热身,因此,我想以类似的方式解决这个问题。但我不确定它到底在哪里减慢了我的应用程序:是程序集的加载(并且我的预取尝试在某种程度上是错误的),还是仍然与 Razor 编译有关?

因为我还知道通过预编译 Razor 视图可以提高性能。在 ASP.NET Core 1 中,我手动启用了此功能,第一个请求明显更快。由于 Microsoft 重新编写了这部分并默认启用了预编译,但我的 Razor DLL 应用程序不会生成名为 {AppName}.Views.dll 的文件(MVC 应用程序有它们),我不确定这是否是问题所在。

【问题讨论】:

  • 一个重要的问题。当您使用发布配置发布时,您是否遇到过这种情况?还是您在开发中遇到这种情况?

标签: c# asp.net-core razor dll asp.net-core-2.1


【解决方案1】:

Some postsblog posts 表示 Razor lib 项目的预编译存在问题。但我记得from the .NET Core docs MvcRazorCompileOnPublish 在 3.0 中已被弃用并删除。它会禁用新的 Razor SDK。这对我来说似乎不是一个可靠的解决方案。

所以我创建了一个空的 Razor 项目并将 csproj 文件与我的 lib 项目进行比较。它显示它引用了我的项目(作为regululr .NET core Core 类库创建)中的Microsoft.NET.Sdk.Razor 而不是Microsoft.NET.Sdk。换完SDK后,我的Debug文件夹里面还有一个Assets.Views.dll文件,表示预编译。

它也是由 NuGet 添加的,可以通过使用 7zip 打开 .nupkg 文件轻松验证。 lib/netcoreapp2.1 文件夹现在也包含 .Views.dll

此解决方案将首次请求渲染时间从约 3 秒缩短至 1.1 秒。快得多,但与没有外部 DLL 的 300 毫秒相比仍然慢得多。我认为这是解决方案的一部分,但似乎还有其他瓶颈会减慢第一个请求。我对如何改善最后一次延迟的其他想法持开放态度。

我目前仅包含来自 Razor DLL 的四个部分视图。一个有 108 行 html,带有一点动态剃刀逻辑和两个注入服务。其他的要小得多,还不包含很多动态逻辑。我也尝试不包括较大的局部视图,没有明显的区别。

我不敢相信包含来自外部 Razor 库的四个相对较小的部分视图会将第一个请求延迟 800 毫秒。当视图在本地位于同一项目中时,情况并非如此。

预加载不是问题

发现a blog entry from Rick Strahl 带有一个列出所有加载程序集的sn-p:

var assemblies = AppDomain.CurrentDomain.GetAssemblies();
foreach (var assembly in assemblies) {
    Console.WriteLine(assembly.GetName());
}

我在使用 Razor DLL 的应用程序的 ConfigureService 中运行了这个。它显示了我的 Razor DLL 文件(Assets Assets.Views)中的两个程序集。我认为是这种情况,因为我获取程序集信息以将其作为EmbeddedFileProvider 传递给RazorViewEngineOptions。但是,它解释了为什么我的预加载尝试对页面生成时间没有任何影响。

【讨论】:

    猜你喜欢
    • 2019-10-14
    • 1970-01-01
    • 2016-10-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-19
    • 2019-06-10
    相关资源
    最近更新 更多