zoukankan      html  css  js  c++  java
  • MVC 测试action的运行速度

    前言

    网络很多文章有关于action的测试机制,本文主要是整理一下思路。

    正文

    假如有一个acion:

    public ActionResult Index()
    {
    	return View();
    }
    

    当然不一定是返回view(),可以是别的。

    一般情况下,计算代码运行的时间可以用Stopwatch。

    但是这里不能,因为:

    public ActionResult Index()
    {
      var result = new Stopwatch();
      result.Start();
      return View();
      result.Stop();
    }
    

    result.Stop(); 是不能运行的。

    除此之外mvc的action有过滤器,个人认为过滤器也属于action的一部分,因为如果要执行一个用户请求,是会去执行里面的过滤器的,所以也需要去计算。

    那么这样我们就可以在过滤器中进行计算。

    先看下过滤器的执行顺序,看下关键几个:

    OnActionExecuting

    在action内的代码执行前执行。

    OnActionExecuted

    在retrun之前执行。

    OnResultExecuting

    retrun前执行。

    OnResultExecuted

    retrun后执行。

    真正的一个action应该是OnActionExecuting到OnResultExecuted区间的代码执行,但是他们可以分别统计出action逻辑代码和渲染代码分别执行的时间,所以分看来写是很好的。

    他们都会用到stopwatch,所以可以肯定的是,一定会调用到相同的代码,所以需要封装一个方法。

    public Stopwatch GetTime(ControllerContext context, string name)
    {
      string key = "timer_" + name;
      if (context.HttpContext.Items.Contains(key))
      {
        return (Stopwatch)context.HttpContext.Items[key];
      }
      var result = new Stopwatch();
      context.HttpContext.Items[key] = result;
      return result;
    }
    

    之所以用ControllerContext ,因为要区分OnAction和OnResult两次的时间计算,而ControllerContext 又贯穿整个action,有些人认为过滤器种的不是ResultExecutedContext和ActionExecutedContext这两个,

    在他们上面按F12,就会发现他们继承了ControllerContext,而ControllerContext又包含了HttpContext ,所以在前端可以直接查看到时间,而不需要调试中去查看。

    弊端:只是考虑了一个action的情况,如果action经过了重定向跳转到另一个action,那么计算的是一串action的时间,所以需要在OnResultExecuted中保存一个当前aciton的执行时间。

    代码如下:

    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
      GetTime(filterContext,"action").Start();
      base.OnActionExecuting(filterContext);
    }
    public override void OnActionExecuted(ActionExecutedContext filterContext)
    {
      GetTime(filterContext, "action").Stop();
      base.OnActionExecuted(filterContext);
    }
    public override void OnResultExecuting(ResultExecutingContext filterContext)
    {
      GetTime(filterContext, "render").Start();
      base.OnResultExecuting(filterContext);
    }
    public override void OnResultExecuted(ResultExecutedContext filterContext)
    {
      var actionTimer = GetTime(filterContext, "action");
      var rendertimer = GetTime(filterContext, "render");
      rendertimer.Stop();
      var str= String.Format("{0},{1},action{2},Result{3}", filterContext.RouteData.Values["Controller"], filterContext.RouteData.Values["action"],   actionTimer.ElapsedMilliseconds.ToString(), rendertimer.ElapsedMilliseconds.ToString());
       //转码
      str = System.Text.Encoding.GetEncoding("GB2312").GetString( Encoding.ASCII.GetBytes(str),0,str.Length);
      //向前端传递运行时间
      filterContext.HttpContext.Response.Headers.Add(filterContext.RouteData.Values["Controller"] + "." + filterContext.RouteData.Values["action"],str);
      base.OnResultExecuted(filterContext);
    }
    
  • 相关阅读:
    Laravel Passport token过期后判断refresh_token是否过期
    js 数组随机排序
    jquery的animate关于background-position属性
    css hack 汇整
    顶部导航--向上滚动的时候出现,向下滚动的时候隐藏
    手机端全局样式表整理(mobile)
    AR专用汉明码
    css常用命名规则
    晚11点
    当 IDENTITY_INSERT 设置为 OFF 时,不能为表‘XXX’中的标识列插入显式值。
  • 原文地址:https://www.cnblogs.com/aoximin/p/13231247.html
Copyright © 2011-2022 走看看