ASP.NET 核心 MVC 中的慢速 DisplayFor 性能
Slow DisplayFor performance in ASP.NET Core MVC
在我当前的应用程序中,我生成了相当长的 table 以显示给用户。我发现它存在一些严重的性能问题,我已经追踪到 @Html.DisplayFor 的使用,但我不完全确定原因。
编辑:我用更简洁和可重现的设置替换了代码示例。
为了隔离问题,我使用 visual studio 中的所有默认设置创建了一个新的 asp.net 核心 MVC 项目,没有进行身份验证。我这样创建了一个视图模型:
public class TestingViewModel
{
public int Id { get; set; }
public string TextValue1 { get; set; }
public string TextValue2 { get; set; }
}
然后添加了一个控制器,用要传递给视图的数据填充视图模型:
public IActionResult TestThings()
{
var list = new List<TestingViewModel>();
for(var i = 0; i < 1000; i++)
list.Add(new TestingViewModel {Id = i, TextValue1 = "Test", TextValue2 = "Test2"});
return View(list);
}
视图是显示数据的最低限度:
@model List<DisplayForTest.ViewModels.TestingViewModel>
@foreach (var item in Model)
{
@Html.DisplayFor(m => item.Id)
@Html.DisplayFor(m => item.TextValue1)
@Html.DisplayFor(m => item.TextValue2)
}
当运行宁此代码时,运行需要一秒钟!罪魁祸首是 DisplayFor。如果我按如下方式更改视图:
@model List<DisplayForTest.ViewModels.TestingViewModel>
@foreach (var item in Model)
{
@item.Id
@item.TextValue1
@item.TextValue2
}
渲染时间为 13 毫秒。很明显,DisplayFor 增加了大量的渲染时间……在我的 PC 上,每次调用将近 0.4 毫秒。虽然单独来看这还不错,但对于列表或其他东西来说,它是一个非常糟糕的选择。
DisplayFor
真的有那么慢吗?还是我用错了?
Is DisplayFor really just that slow? Or am I using it incorrectly?
评估和执行 lambda 表达式需要一些开销。首先,框架必须 validate it, then evaluate it。 我在这里有点推测,但似乎这就是性能问题的来源;这两种方法都需要反思。
我使用过的所有其他显示方法(ValueFor
、DisplayTextFor
等)在您的示例中具有相同的性能效果。
我不能代表 MVC 团队说明为什么将它用于默认脚手架,但它对我来说确实有意义。 DisplayFor
可以处理两种最常见的用例(显示 属性 的值,以及使用自定义模板显示 属性 的值),并且在大多数情况下表现相当好.
在这种情况下,我没有发现仅使用原始值(基本上 .ToString
ing 它)或在 Html.Encode
/Html.Raw
方法中使用它的问题取决于您要查找的内容。
在 Raspberry PI 上使用 .Net Core,我遇到了同样的问题。表演真的很糟糕。我使用了 dotTrace,发现反射使用了很多时间。
基于以下article,我能够加速应用程序。
在我当前的应用程序中,我生成了相当长的 table 以显示给用户。我发现它存在一些严重的性能问题,我已经追踪到 @Html.DisplayFor 的使用,但我不完全确定原因。
编辑:我用更简洁和可重现的设置替换了代码示例。
为了隔离问题,我使用 visual studio 中的所有默认设置创建了一个新的 asp.net 核心 MVC 项目,没有进行身份验证。我这样创建了一个视图模型:
public class TestingViewModel
{
public int Id { get; set; }
public string TextValue1 { get; set; }
public string TextValue2 { get; set; }
}
然后添加了一个控制器,用要传递给视图的数据填充视图模型:
public IActionResult TestThings()
{
var list = new List<TestingViewModel>();
for(var i = 0; i < 1000; i++)
list.Add(new TestingViewModel {Id = i, TextValue1 = "Test", TextValue2 = "Test2"});
return View(list);
}
视图是显示数据的最低限度:
@model List<DisplayForTest.ViewModels.TestingViewModel>
@foreach (var item in Model)
{
@Html.DisplayFor(m => item.Id)
@Html.DisplayFor(m => item.TextValue1)
@Html.DisplayFor(m => item.TextValue2)
}
当运行宁此代码时,运行需要一秒钟!罪魁祸首是 DisplayFor。如果我按如下方式更改视图:
@model List<DisplayForTest.ViewModels.TestingViewModel>
@foreach (var item in Model)
{
@item.Id
@item.TextValue1
@item.TextValue2
}
渲染时间为 13 毫秒。很明显,DisplayFor 增加了大量的渲染时间……在我的 PC 上,每次调用将近 0.4 毫秒。虽然单独来看这还不错,但对于列表或其他东西来说,它是一个非常糟糕的选择。
DisplayFor
真的有那么慢吗?还是我用错了?
Is DisplayFor really just that slow? Or am I using it incorrectly?
评估和执行 lambda 表达式需要一些开销。首先,框架必须 validate it, then evaluate it。 我在这里有点推测,但似乎这就是性能问题的来源;这两种方法都需要反思。
我使用过的所有其他显示方法(ValueFor
、DisplayTextFor
等)在您的示例中具有相同的性能效果。
我不能代表 MVC 团队说明为什么将它用于默认脚手架,但它对我来说确实有意义。 DisplayFor
可以处理两种最常见的用例(显示 属性 的值,以及使用自定义模板显示 属性 的值),并且在大多数情况下表现相当好.
在这种情况下,我没有发现仅使用原始值(基本上 .ToString
ing 它)或在 Html.Encode
/Html.Raw
方法中使用它的问题取决于您要查找的内容。
在 Raspberry PI 上使用 .Net Core,我遇到了同样的问题。表演真的很糟糕。我使用了 dotTrace,发现反射使用了很多时间。
基于以下article,我能够加速应用程序。