• c# 统计方法执行时间,计算缓存读取数据方法的命中率


     一.              构造StopwatchPool 

    System.Diagnostics命名空间中dot net framework为我们提供了精确计算代码执行时间的类Stopwatch;因为我们可能频繁使用Stopwatch类的实例,所以我们在此做一个简单的对象池,尽量降低非方法执行时间对程序性能的影响。 

    StopwatchPool类的静态字段List<StopwatchWithUseState> _watchList中包含了系统中初始化好的StopwatchWithUseState实例;StopwatchWithUseState 实例中是Stopwatch的实例,和一个它是否正在被使用的字段。当需要新的Stopwatch实例使直接调用StopwatchPool的静态方法NewStopwatch()即可,注意在使用完Stopwatch实例之后需要调用ReleaseWatch(Stopwatch)释放掉Stopwatch。具体代码会在文章结尾给出,其类图如下:

    二.              统计方法执行时间 

    类图如下:

    MethodPerfMonitor的关键实现是在进入一个方法时执行EnterMethod()方法,该方法会申请一个Stopwatch实例,并启动实例,记录方法执行次数;在方法执行结束时调用FinishMethod()方法,记录方法执行时间,并释放Stopwatch实例。其关键代码如下

    /// <summary>
            
    /// 在方法开始执行时调用此方法
            
    /// </summary>

            [Conditional(EnablePerfMonitor.CompilerSymbal)]
            
    public virtual void EnterMethod()
            
    {
                
    lock (instanceLock)
                
    {
                    _execCount
    ++;
                    
    if (_startRunTime == DateTime.MinValue)
                    
    {
                        _startRunTime 
    = DateTime.Now;
                    }

                }

                _watch 
    = StopwatchPool.NewStopwatch();
                _watch.Start();
            }



            
    /// <summary>
            
    /// 在方法完成之前调用,必须调用,若不调用会导致申请的Stopwatch得不到释放
            
    /// 最好在try{}finally{}的finally中释放
            
    /// </summary>

            [Conditional(EnablePerfMonitor.CompilerSymbal)]
            
    public virtual void FinishMethod()
            
    {
                
    lock (instanceLock)
                
    {
                    TotalRunTime 
    += TimeSpan.FromTicks(_watch.ElapsedTicks);
                }

                StopwatchPool.ReleaseWatch(_watch);
            }

    大家可以看到在两个方法的前面都使用了Conditional特性,这样可以在编译时方便的启用或者禁用方法执行时间统计。

    在这个类中还提供了一个静态方法RegisterMonitor(string methodFullName)这个方法会返回一个MethodPerfMonitor类的实例,若该类的静态字段_methodMonitorTable中有方法全名对应的MethodPerfMonitor实例,则直接返回,否则将新生成的实例保存在该类的一个静态字段中。这样保证一个实例对应一个方法的统计。 

    三.              统计缓存方法的执行时间和缓存命中率 

    我们需要一个新的类来统计方法的缓存命中情况,CachableMethodPerfMonitor该类从MethodPerfMonitor继承,该类只多了一个功能统计缓存的命中率;在方法执行结束时执行FinishMethod时需要指定这一次执行是否命中了缓存。并添加方法执行时间和缓存命中时的执行时间。其关键实现如下:

    /// <summary>
            
    /// 在方法结束时调用
            
    /// </summary>
            
    /// <param name="isHitCache">是否命中缓存</param>

            [Conditional(EnablePerfMonitor.CompilerSymbal)]
            
    public void FinishMethod(bool isHitCache)
            
    {
                
    lock (instanceLock)
                
    {
                    TimeSpan execTimespan 
    = TimeSpan.FromTicks(_watch.ElapsedTicks);
                    
    if (isHitCache)
                    
    {
                        CacheRunTime 
    += execTimespan;
                        _hitTimes
    ++;
                    }

                    TotalRunTime 
    += execTimespan;
                }


                StopwatchPool.ReleaseWatch(_watch);
            }

    四.              如何使用 

    请看如下实例代码。有问题欢迎提出。

    相关源码下载

  • 相关阅读:
    Single Number 解答
    Minimum Size Subarray Sum 解答
    Valid Anagram 解答
    Count Primes 解答
    fullCalendar 日历显示每天数据调用方法实践
    jqGrid列的统计
    关于 asp.net Web Api 上传文件请求内容过大404错误记录
    My97DatePicker只显示月份
    js 宏微任务执行顺序
    git 等官网下载慢方法
  • 原文地址:https://www.cnblogs.com/yukaizhao/p/method_performance.html
Copyright © 2020-2023  润新知