从ASP.NET Core 2.1中的类库导入Razor视图时,第一个请求很慢

时间:2019-10-04 17:33:24

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

在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应用程序在其中包含它们),因此我不确定这可能是问题所在。

1 个答案:

答案 0 :(得分:0)

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

因此,我创建了一个空的Razor项目,并将csproj文件与我的lib项目进行了比较。它表明它引用了我项目中的Microsoft.NET.Sdk.Razor而不是Microsoft.NET.Sdk(作为常规.NET核心Core类库创建)。更新SDK之后,我的Debug文件夹中还包含一个Assets.Views.dll文件,该文件指示已进行预编译。

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

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

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

我不敢相信,从外部Razor lib获得的四个相对较小的局部视图会将第一个请求延迟了800ms。当视图位于同一项目的本地时,情况并非如此。

预加载不是问题

找到a blog entry from Rick Strahl并带有列出所有已加载程序集的代码段:

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

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