对老赵写的简单性能计数器的修改

对老赵写的简单性能计数器的修改

    早上看到老赵写的这个性能计数器,感觉很实用,不过老赵用了很多.C# 3.0 的新语法,还用了 VISTA 和 Server 2008 下特有的Win32 API,对于还在用C#2.0 或者还工作在 XP 或者 Server 2003 下的兄弟们,只能望代码心叹了。应老赵的要求,我修改了他的代码,增加了对低版本C# 和 低版本windows 操作系统的支持。

    老赵的原文: 一个简单的性能计数器:CodeTimer

    修改说明

    1. 采用 接口 取代了原代码中的 Lambda 表达式

    2. 采用 GetThreadTimes 这个API 函数替代了原代码中的 QueryThreadCycleTime

    这里需要说明的是 GetThreadTimes 给出了线程在内核态和用户态占用的时间,单位是 100 ns。两个时间的总和就是线程占用的CPU时间。这个API的时间精度我看了一些资料似乎没有达到 100ns. 所以GetThreadTimes 这个API函数的进度没有 QueryThreadCycleTime 高。

    下面是我修改后的代码

    注释1: 2009-03-11 增加委托的调用,修改 GC.Collect 参数,兼容.Net 2.0.  增加每次调用时间统计 

    增加了委托调用后,我发现同样是测试空函数,采用接口比采用委托效率要略高一些,这和我的预计基本吻合,因为委托不是单纯的函数调用,具体原理超出本文范围,我就不多说了。

 

 

using  System;
using  System.Collections.Generic;
using  System.Text;
using  System.Diagnostics;
using  System.Threading;
using  System.Runtime.InteropServices;
  
 
    
public   interface  IAction
    
{
        
void  Action();
    }


    
public   static   class  CodeTimer
    
{
        [DllImport(
" kernel32.dll " , SetLastError  =   true )]
        
static   extern   bool  GetThreadTimes(IntPtr hThread,  out   long  lpCreationTime,
           
out   long  lpExitTime,  out   long  lpKernelTime,  out   long  lpUserTime);

        [DllImport(
" kernel32.dll " )]
        
static   extern  IntPtr GetCurrentThread();

        
public   delegate   void  ActionDelegate();

        
private   static   long  GetCurrentThreadTimes()
        
{
            
long  l;
            
long  kernelTime, userTimer;
            GetThreadTimes(GetCurrentThread(), 
out  l,  out  l,  out  kernelTime, 
               
out  userTimer);
            
return  kernelTime  +  userTimer;
        }


        
static  CodeTimer()
        
{
            Process.GetCurrentProcess().PriorityClass 
=  ProcessPriorityClass.High;
            Thread.CurrentThread.Priority 
=  ThreadPriority.Highest;

        }


        
public   static   void  Time( string  name,  int  iteration, ActionDelegate action)
        
{
            
if  (String.IsNullOrEmpty(name))
            
{
                
return ;
            }


            
if  (action  ==   null )
            
{
                
return ;
            }


            
// 1. Print name
            ConsoleColor currentForeColor  =  Console.ForegroundColor;
            Console.ForegroundColor 
=  ConsoleColor.Yellow;
            Console.WriteLine(name);


            
//  2. Record the latest GC counts
            
// GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced);
            GC.Collect(GC.MaxGeneration);
            
int [] gcCounts  =   new   int [GC.MaxGeneration  +   1 ];
            
for  ( int  i  =   0 ; i  <=  GC.MaxGeneration; i ++ )
            
{
                gcCounts[i] 
=  GC.CollectionCount(i);
            }


            
//  3. Run action
            Stopwatch watch  =   new  Stopwatch();
            watch.Start();
            
long  ticksFst  =  GetCurrentThreadTimes();  // 100 nanosecond one tick

            
for  ( int  i  =   0 ; i  <  iteration; i ++ ) action();
            
long  ticks  =  GetCurrentThreadTimes()  -  ticksFst;
            watch.Stop();

            
//  4. Print CPU
            Console.ForegroundColor  =  currentForeColor;
            Console.WriteLine(
" /tTime Elapsed:/t/t "   +  
               watch.ElapsedMilliseconds.ToString(
" N0 " +   " ms " );
            Console.WriteLine(
" /tTime Elapsed (one time): "   +  
               (watch.ElapsedMilliseconds 
/  iteration).ToString( " N0 " +   " ms " );

            Console.WriteLine(
" /tCPU time:/t/t "   +  (ticks  *   100 ).ToString( " N0 "
               
+   " ns " );
            Console.WriteLine(
" /tCPU time (one time):/t "   +  (ticks  *   100   /  
               iteration).ToString(
" N0 " +   " ns " );

            
//  5. Print GC
             for  ( int  i  =   0 ; i  <=  GC.MaxGeneration; i ++ )
            
{
                
int  count  =  GC.CollectionCount(i)  -  gcCounts[i];
                Console.WriteLine(
" /tGen  "   +  i  +   " : /t/t/t "   +  count);
            }


            Console.WriteLine();

        }


        
public   static   void  Time( string  name,  int  iteration, IAction action)
        
{
            
if  (String.IsNullOrEmpty(name))
            
{
                
return ;
            }


            
if  (action  ==   null )
            
{
                
return ;
            }


            
// 1. Print name
            ConsoleColor currentForeColor  =  Console.ForegroundColor;
            Console.ForegroundColor 
=  ConsoleColor.Yellow;
            Console.WriteLine(name);


            
//  2. Record the latest GC counts
            
// GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced);
            GC.Collect(GC.MaxGeneration);
            
int [] gcCounts  =   new   int [GC.MaxGeneration  +   1 ];
            
for  ( int  i  =   0 ; i  <=  GC.MaxGeneration; i ++ )
            
{
                gcCounts[i] 
=  GC.CollectionCount(i);
            }


            
//  3. Run action
            Stopwatch watch  =   new  Stopwatch();
            watch.Start();
            
long  ticksFst  =  GetCurrentThreadTimes();  // 100 nanosecond one tick
            
            
for  ( int  i  =   0 ; i  <  iteration; i ++ ) action.Action();
            
long  ticks  =  GetCurrentThreadTimes()  -  ticksFst;
            watch.Stop();

            
//  4. Print CPU
            Console.ForegroundColor  =  currentForeColor;
            Console.WriteLine(
" /tTime Elapsed:/t/t "   +  
               watch.ElapsedMilliseconds.ToString(
" N0 " +   " ms " );
            Console.WriteLine(
" /tTime Elapsed (one time): "   +  
               (watch.ElapsedMilliseconds 
/  iteration).ToString( " N0 " +   " ms " );

            Console.WriteLine(
" /tCPU time:/t/t "   +  (ticks  *   100 ).ToString( " N0 "
                
+   " ns " );
            Console.WriteLine(
" /tCPU time (one time):/t "   +  (ticks  *   100   /  
                iteration).ToString(
" N0 " +   " ns " );

            
//  5. Print GC
             for  ( int  i  =   0 ; i  <=  GC.MaxGeneration; i ++ )
            
{
                
int  count  =  GC.CollectionCount(i)  -  gcCounts[i];
                Console.WriteLine(
" /tGen  "   +  i  +   " : /t/t/t "   +  count);
            }


            Console.WriteLine();

        }

    }

 

测试类

 

 

     public   class  TestSleep3000 : IAction
    {
        
#region  IAction Members

        
public   void  Action()
        {
            Thread.Sleep(
3000 );
        }

        
#endregion
    }


    
public   class  TestEmptyMethod : IAction
    {
        
#region  IAction Members

        
public   void  Action()
        {
        }

        
#endregion
    }

    
public   class  TestStringConcat : IAction
    {
        
string  s  =   "" ;

        
#region  IAction Members

        
public   void  Action()
        {
            s 
+=   " a " ;
        }

        
#endregion
    }

    
public   class  TestStringBuilderConcat : IAction
    {
        StringBuilder s 
=   new  StringBuilder();

        
#region  IAction Members

        
public   void  Action()
        {
            s.Append (
" a " );
        }

        
#endregion
    }

 

测试代码

采用接口 

            CodeTimer.Time( " Thread Sleep " 1 new  TestSleep3000());
            CodeTimer.Time(
" Thread Sleep " 10000000 new  TestEmptyMethod());
            CodeTimer.Time(
" String Concat " 100000 new  TestStringConcat());
            CodeTimer.Time(
" StringBuilder Conca " 100000
                 
new  TestStringBuilderConcat()); 

 

测试结果

 

 

Thread Sleep
        Time Elapsed:           2,997ms
        Time Elapsed (one time):2,997ms
        CPU time:               0ns
        CPU time (one time):    0ns
        Gen 0:                  0
        Gen 1:                  0
        Gen 2:                  0

Empty Method
        Time Elapsed:           138ms
        Time Elapsed (one time):0ms
        CPU time:               125,000,000ns
        CPU time (one time):    12ns
        Gen 0:                  0
        Gen 1:                  0
        Gen 2:                  0

String Concat
        Time Elapsed:           10,547ms
        Time Elapsed (one time):0ms
        CPU time:               10,546,875,000ns
        CPU time (one time):    105,468ns
        Gen 0:                  4102
        Gen 1:                  2661
        Gen 2:                  2545

StringBuilder Conca
        Time Elapsed:           4ms
        Time Elapsed (one time):0ms
        CPU time:               0ns
        CPU time (one time):    0ns
        Gen 0:                  0
        Gen 1:                  0
        Gen 2:                  0

 

采用委托

 

CodeTimer.Time( " Thread Sleep " 1 delegate ()  { Thread.Sleep( 3000 ); } );
CodeTimer.Time(
" Empty Method " 10000000 delegate ()  { } );

string  a  =   "" ;

CodeTimer.Time(
" String Concat " 100000 delegate ()  { a  +=   " a " ; } );

StringBuilder s 
=   new  StringBuilder();
CodeTimer.Time(
" StringBuilder Conca " 100000 delegate ()  { s.Append( " a " ); } ); 

 

 测试结果

 

Thread Sleep
        Time Elapsed:           2,989ms
        Time Elapsed (one time):2,989ms
        CPU time:               0ns
        CPU time (one time):    0ns
        Gen 0:                  0
        Gen 1:                  0
        Gen 2:                  0

Empty Method
        Time Elapsed:           156ms
        Time Elapsed (one time):0ms
        CPU time:               156,250,000ns
        CPU time (one time):    15ns
        Gen 0:                  0
        Gen 1:                  0
        Gen 2:                  0

String Concat
        Time Elapsed:           10,425ms
        Time Elapsed (one time):0ms
        CPU time:               10,406,250,000ns
        CPU time (one time):    104,062ns
        Gen 0:                  4102
        Gen 1:                  2661
        Gen 2:                  2545

StringBuilder Conca
        Time Elapsed:           4ms
        Time Elapsed (one time):0ms
        CPU time:               0ns
        CPU time (one time):    0ns
        Gen 0:                  0
        Gen 1:                  0
        Gen 2:                  0

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值