Recently when working with an ASP.NET Core project I had a page that was taking an unnecessarily long time to render. Looking at my code I couldn't figure out what I was doing wrong, the query returned fast, and although I was working to display about 1,000 rows in an HTML table, it shouldn't be taking seconds when the query returned in 22ms. Upon deeper review, I uncovered a bug that had been a silent killer of performance in multiple applications.
When using the default scaffolding templates to render "list" views within Visual Studio the template will output content using a snippet similar to the following.
@Html.DisplayFor(modelItem => item.ProductName)
This seems to be an innocent enough process. We want ASP.NET to make sure that we get a solid display based on the type, allowing us to use templates to control the display.
Although this is the recommended approach, it is the use of Html.DisplayFor that is causing the slowdown. Doing a performance trace on the page load, you will find that all of the time spent is concentrated inside of this method, not something that we can optimize as a user.
Once I was able to fully track this down I submitted a bug report on GitHub. Others have confirmed the behavior, however, we don't yet have a solution in place.
The workaround for this is quite simple, rather than using Html.DisplayFor, simply reference your item directly. Such as the following from the prior example.
This simple process will work, and you should see a nice performance improvement. I seem to notice a performance impact anytime I have a view that renders more than 400-500 items using Html.DisplayFor. Your exact performance hit will vary depending on a number of factors. However, the workaround solution seems to be stable regardless of the number of elements.
Microsoft is looking at this item, and it is scheduled for triage, but for the time being, it might be helpful to keep an eye on this one! Hope it helps!