Razor视图的性能分析

问题描述 投票:0回答:1

我正在开发一个项目,我们在这个项目中呈现一种文章列表,其中包含大量可选图像和文本属性,以及所有“花式”非表格布局,这些布局适应现有/缺失属性并添加一些随机性。客户想要一个随意的外观,我们最终得到了一个深度为4和3-10的每个级别的剃刀模板。每个模板都非常简单,没有“魔法”。

在加载测试期间,我们发现对于大型文章列表,我们在视图渲染中存在性能问题。渲染5篇文章需要20ms,但渲染60需要1s。

有没有一种智能的方法来衡量每个模板渲染持续时间?我想避免手动添加Stopwatches。有框架方式吗?是否有关于如何调试此类问题的建议?我找不到任何东西。

c# performance razor asp.net-core .net-core
1个回答
0
投票

刚刚找到了一个很好的解决方案

public class RazorPerformanceDiagnosticListener
{
    private readonly IDictionary<string, TemplatePerformanceHolder> _timers = new ConcurrentDictionary<string, TemplatePerformanceHolder>();

    [DiagnosticName("Microsoft.AspNetCore.Mvc.Razor.BeginInstrumentationContext")]
    public virtual void OnBeginInstrumentationContext(HttpContext httpContext, string path, int position, int length, bool isLiteral)
    {
        if (_timers.ContainsKey(path))
        {
            _timers[path].ContextDepth++;
        }
        else
        {
            _timers[path] = new TemplatePerformanceHolder(){ContextDepth = 1, Stopwatch = Stopwatch.StartNew() };
        }
    }

    [DiagnosticName("Microsoft.AspNetCore.Mvc.Razor.EndInstrumentationContext")]
    public virtual void OnEndInstrumentationContext(HttpContext httpContext, string path)
    {
        _timers[path].ContextDepth--;

        if (_timers[path].ContextDepth == 0)
        {
            _timers[path].Stopwatch.Stop();
            //log _timers[path].Stopwatch.Elapsed
            _timers.Remove(path);
        }
    }
}

public class TemplatePerformanceHolder
{
    public Stopwatch Stopwatch;
    public int ContextDepth;
}

在Startup.cs中

using System.Diagnostics;

public void Configure(DiagnosticListener diagnosticListener)
{
    diagnosticListener.SubscribeWithAdapter(new RazorPerformanceDiagnosticListener());
}

如果您想知道为什么需要跟踪这个上下文深度:这些BeginInstrumentationContext事件在一个razor模板中被触发多次(因此是EndInstrumentationContext),因此每个模板都有一个堆栈。

另请注意,此代码将遇到并发请求(或并行化模板呈现)问题。要解决它,您需要使HttpContext和可能的线程id成为Dictionary键的一部分。但我不需要“生产就绪”代码,所以要小心。

基于this

© www.soinside.com 2019 - 2024. All rights reserved.