【问题标题】:How much computation is behind a HttpContext.Current call?HttpContext.Current 调用背后有多少计算量?
【发布时间】:2010-01-08 21:42:29
【问题描述】:

贵吗?

我正在开发一个直接呈现给 Response.Output 的 HtmlHelper,以节省不必要的字符串创建,我需要在以下两者之间进行选择:

<% Validator.RenderClient(Response.Output); %>

<% Validator.RenderClient(); %>

并从 HttpContext.Current.Response 中获取 textWriter

【问题讨论】:

    标签: asp.net-mvc performance


    【解决方案1】:

    @道金斯

    100 次运行太少,您需要运行大约 10000 次并重复它,然后取其平均值以获得可靠的结果。在您的示例中,误差幅度很大,但这是正确的方法。

    这就是我所做的:

    var results1 = new List<long>();
    var results2 = new List<long>();
    
    for (int j = 0; j < 100; j++)
    {
        var sp = new System.Diagnostics.Stopwatch();
    
        // With HttpContext.Current: 
        sp.Start();
        for (int i = 0; i < 10000; i++)
        {
            HttpContext.Current.Response.Output.Write(i);
        }
        sp.Stop();
    
        results1.Add(sp.ElapsedTicks);
    
        // Without: 
        TextWriter output2 = HttpContext.Current.Response.Output;
        sp.Reset();
    
        sp.Start();
        for (int i = 0; i < 10000; i++)
        {
            output2.Write(i);
        }
        sp.Stop();
    
        HttpContext.Current.Response.Clear();
    
        results2.Add(sp.ElapsedTicks);
    }
    
    results1.Sort();
    results2.Sort();
    
    HttpContext.Current.Response.Write(string.Format("HttpContext.Current={0:0.000}ms, Local variable={1:0.000}ms, R={2:0.0%}<br/>", results1[results1.Count / 2] / (double)TimeSpan.TicksPerMillisecond, results2[results2.Count / 2] / (double)TimeSpan.TicksPerMillisecond, (double)results1[results1.Count / 2] / (double)results2[results2.Count / 2]));
    

    您的结果表明存在 18% 的性能差异,这表明它更昂贵但下降了 8%。

    我重新计算了几次,得出了 10% 的差异,误差小于 1%。

    它稳定下来:

    HttpContext.Current=0,536ms, Local variable=0,486ms, R=110,2% 
    

    无论如何,HttpContext.Current 会造成严重的性能问题,您需要将其调用方式超过每个请求 10000(成本主要由 Response.Write 调用构成)。这很可能不会发生。

    【讨论】:

      【解决方案2】:

      来自反射器

      public static HttpContext get_Current()
      {
          return (ContextBase.Current as HttpContext);
      }
      

      调用 ContextBase 哪个调用

      public static object HostContext
      {
          get
          {
              object hostContext = 
                Thread.CurrentThread.GetIllogicalCallContext().HostContext;
              if (hostContext == null)
              {
                  hostContext = GetLogicalCallContext().HostContext;
              }
              return hostContext;
          }
      

      ...

      所以有一些线程“东西”正在发生;具体的我不太清楚。

      【讨论】:

      • 出于某种原因,我发现有趣的是,他们似乎更喜欢不合逻辑的调用上下文返回的内容,而不是逻辑调用上下文的返回内容(无论这些内容是什么)。
      【解决方案3】:

      它一点也不密集。我不知道为什么我没有第一次尝试这个:

              System.Diagnostics.Stopwatch sp = new System.Diagnostics.Stopwatch();
      
              // With HttpContext.Current:
              sp.Start();
              for (int i = 0; i < 100; i++)
              {
                  HttpContext.Current.Response.Output.Write(i.ToString());
              }
              sp.Stop();
              long result1 = sp.ElapsedTicks;
      
              // Without:
              TextWriter output2 = HttpContext.Current.Response.Output;
              sp.Reset();
              sp.Start();
              for (int i = 0; i < 100; i++)
              {
                  output2.Write(i.ToString());
              }
              sp.Stop();
              long result2 = sp.ElapsedTicks; 
      

      我的电脑结果是:

      result1= 395 滴答 结果2= 332 滴答声

      所以它非常快!

      【讨论】:

      • 我对我们进行性能测试的方式有疑问,请参阅下面的答案。您的回答正确,但结果不准确(统计上可行)。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多