In my current application I'm generating a fairly lengthy table to display to the user. I've been seeing some serious performance issues with it, which I've tracked down to usage of @Html.DisplayFor, and I'm not entirely sure why.
Edit: I've replaced the code sample with a more concise and reproducible setup.
In order to isolate the issue, I have created a new asp.net core MVC project using all default settings in visual studio, with no authentication. I created a view model as such:
public class TestingViewModel
{
public int Id { get; set; }
public string TextValue1 { get; set; }
public string TextValue2 { get; set; }
}
Then added a controller which fills the view model with data to pass to the view:
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);
}
The view is the bare minimum possible to display the data:
@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)
}
When running this code, it takes over one second to run! The culprit is the DisplayFor. If I change the view as follows:
@model List<DisplayForTest.ViewModels.TestingViewModel>
@foreach (var item in Model)
{
@item.Id
@item.TextValue1
@item.TextValue2
}
This renders in 13ms. It's clear DisplayFor is adding a huge amount of time to rendering... on my PC that's nearly 0.4ms per call. While that's not bad in isolation, it makes it a pretty bad choice for lists or other things.
Is DisplayFor
really just that slow? Or am I using it incorrectly?
Is DisplayFor really just that slow? Or am I using it incorrectly?
It takes a bit of overhead to evaluate and execute lambda expressions. First the framework has to validate it, then evaluate it. I am speculating a bit here, but it seems likely this is where the performance concerns are coming from; both of these methods require reflection.
All of the other display methods I've played with (ValueFor
, DisplayTextFor
, etc.) have the same performance effect in your example.
I can't speak for the MVC team as to why it is used for the default scaffolding, but it does make sense to me. DisplayFor
can handle both of the most common use cases (displaying the value of a property, and displaying the value of a property using a custom template), and performs reasonably well in most cases.
In this case, I don't see a problem with just using the raw value (basically .ToString
ing it), or using it within an Html.Encode
/Html.Raw
method depending on what you're looking for.
Using .Net Core on a Raspberry PI, I experienced the same problem. The performance went really bad. I used dotTrace and found that the reflection uses much of the time.
Based on the following article, I was able to speedup the application.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With