我正在做一个项目,在这个项目中,我们呈现了一种文章列表,有很多可选的图像和文本属性,所有这些都是“花哨”的非表格布局,可以适应现有的/缺失的属性,并添加一些随机性。客户想要一个随意的外观,我们最终得到了每个级别上深度为4和3-10的剃刀模板的大树。每个模板都非常简单,没有什么“魔法”。
在负载测试期间,我们发现对于大型文章列表,我们在视图呈现方面存在性能问题。渲染5篇文章需要20毫秒,但渲染60篇文章需要1秒。
有没有一种聪明的方法来衡量每个模板的渲染持续时间?我希望避免手动添加Stopwatches。有没有框架的方法?一般情况下,有没有关于如何调试这类问题的建议?我什么也找不到。
发布于 2018-09-07 16:33:00
我自己找到了一个很好的解决方案:
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事件在一个剃刀模板(EndInstrumentationContext也是如此)中被多次触发,因此每个模板都有一个堆栈。
还要记住,这段代码会遇到并发请求(或并行模板渲染)的问题。要解决这个问题,您需要使HttpContext和线程id成为字典键的一部分。但是我不需要“生产就绪”的代码,所以要小心。
基于this。
https://stackoverflow.com/questions/51799808
复制相似问题