设计之美——反射测试

  由于反射的灵活性,总是尝试多使用用于减少代码的开支,但是凡事总是有代价的,反射的效率确实让人汗颜。有文章說测试效率底了250多倍,这个确实有点让人无法忍受了,但是今天在查关于C#函数指针的时候,却让我眼前一亮,事情总是有解决办法的,如果不失反射的灵活又拿回大部分效率,也许大家都会感兴趣的,这里我就来给大家一个测试。

  开头的几个测试沿用了网上的几个小测试大家直接看代码

 

     public   class  CTester : ICloneable
    
{
        
public CTester()
        
{
            a 
= 10;
        }


        
public void test1()
        
{
            a 
= (a - 0.0001* 1.0001;
        }

        
private double a;
        
public double geta() return a; }

        
public object Clone()
        
{
            
return this.MemberwiseClone();
        }

    }

 

这是主题的测试类,没什么好说的了 开始两个简单测试。

 


        
public   void  test1()
        
{

            DateTime now 
= DateTime.Now;
            
            
for (int i = 0; i < 10000; i++)
            
{
                
for (int j = 0; j < 100; j++)
                
{
                    CTester aTest 
= new CTester();
                    
                    aTest.test1();
                }

            }


            TimeSpan spand 
= DateTime.Now - now;
            Console.WriteLine(
"test1 time past " + spand.ToString());
        }


        
public   void  test2()
        
{

            DateTime now 
= DateTime.Now;
            Type theTest 
= Type.GetType("CmdWebBrowse.CTester");

            
for (int i = 0; i < 10000; i++)
            
{
                
for (int j = 0; j < 100; j++)
                
{
                    
object theobj = theTest.InvokeMember(null, BindingFlags.CreateInstance
      , 
nullnullnull);

                    
//theTest.GetMethod("test1").Invoke(theobj,null); 

                }

            }


            TimeSpan spand 
= DateTime.Now - now;
            Console.WriteLine(
"test2 只有反射生成 time past " + spand.ToString());
        }

 

 

为了更容易看到结果我把循环加到了100w次,我的迅驰二笔记本上的时间是

test1 time past 00:00:00.0468750
test2 只有反射生成 time past 00:00:02.2656250

果然差距很大 但是这里就是要来解决这个问题的。

反射生成的速度确实无法让人忍受。但是对于一个对象还有什么办法么?

既然无法直接new 那么我们是否可以拷贝一个?

好的实现克隆,大家也看到了 开头的函数有克隆函数我们来用下

 

         public   void  test5()
        
{

            Type theTest 
= Type.GetType("CmdWebBrowse.CTester");


            DateTime now 
= DateTime.Now;
            CTester theobj 
= theTest.InvokeMember(null, BindingFlags.CreateInstance
nullnullnullas CTester;
            


            
for (int i = 0; i < 10000; i++)
            
{
                
for (int j = 0; j < 100; j++)
                
{

                    
object test = theobj.Clone() ;
                    theTest.GetMethod(
"test1").Invoke(test, null); 

                }

            }


            TimeSpan spand 
= DateTime.Now - now;
            Console.WriteLine(
"test5 反射一个 克隆对象 执行 反射方法 time past " + spand.ToString());
        }

test5 反射一个 克隆对象 执行 反射方法 time past 00:00:04.1093750

看不出来测试时间,由于使用了反射委托 暂时放这里

继续看测试

 

         public   void  test4()
        
{
            
            DateTime now 
= DateTime.Now;

            Type theTest 
= Type.GetType("CmdWebBrowse.CTester");
            CTester theobj 
= theTest.InvokeMember(null, BindingFlags.CreateInstance
                  , 
nullnullnullas CTester;

            
for (int i = 0; i < 10000; i++)
            
{
                
for (int j = 0; j < 100; j++)
                
{

                    CTester test 
= theobj.Clone() as CTester;
                    test.test1();

                }

            }


            TimeSpan spand 
= DateTime.Now - now;
            Console.WriteLine(
"test4 克隆反射对象 并且直接执行 time past " + spand.ToString());
        }

test4 克隆反射对象 并且直接执行 time past 00:00:00.2031250

看起来让人很满意,但是仅仅是反射一个对象,然后克隆调用一个方法就够了?如果是有公共接口这里就够了,我觉得。但是显然你也许不满足,是的至少我不满足,继续看。

尝试使用一个委托来进行方法调用

         public   delegate   void  testdel();
        

        
public   void  test3()
        
{
            Type theTest 
= Type.GetType("CmdWebBrowse.CTester");
            CTester theobj 
= theTest.InvokeMember(null, BindingFlags.CreateInstance
nullnullnullas CTester;
           

            DateTime now 
= DateTime.Now;
            testdel method;
             
             
for (int i = 0; i < 10000; i++)
             
{
                 
for (int j = 0; j < 100; j++)
                 
{
                     method 
= (testdel)Delegate.CreateDelegate(typeof(testdel), theobj, "test1");
                     method();
                 }

             }


             TimeSpan spand 
= DateTime.Now - now;
             Console.WriteLine(
"test3 委托方法执行 time past " + spand.ToString());
        }

test3 委托方法执行 time past 00:00:07.0937500

动态创建委托,速度更无法看了为什么有如此之慢!

 

         public   void  test5()
        
{

            Type theTest 
= Type.GetType("CmdWebBrowse.CTester");


            DateTime now 
= DateTime.Now;
            CTester theobj 
= theTest.InvokeMember(null, BindingFlags.CreateInstance
nullnullnullas CTester;
            


            
for (int i = 0; i < 10000; i++)
            
{
                
for (int j = 0; j < 100; j++)
                
{

                    
object test = theobj.Clone() ;
                    theTest.GetMethod(
"test1").Invoke(test, null); 

                }

            }


            TimeSpan spand 
= DateTime.Now - now;
            Console.WriteLine(
"test5 反射一个 克隆对象 执行 反射方法 time past " + spand.ToString());
        }



test5 反射一个 克隆对象 执行 反射方法 time past 00:00:04.1093750

嗯 不管如何 反射的方法的速度还是太慢

看最后一个测试。。


        
public   void  test6()
        
{

            DateTime now 
= DateTime.Now;
            Type theTest 
= Type.GetType("CmdWebBrowse.CTester");
            CTester theobj 
= theTest.InvokeMember(null, BindingFlags.CreateInstance
nullnullnullas CTester;


            testdel method;
            method 
= (testdel)Delegate.CreateDelegate(typeof(testdel), theobj, "test1");
            
for (int i = 0; i < 10000; i++)
            
{
                
for (int j = 0; j < 100; j++)
                
{
                    
                    method();
                }

            }


            TimeSpan spand 
= DateTime.Now - now;
            Console.WriteLine(
"test6 委托方法重复执行 time past " + spand.ToString());
        }


test6 委托方法重复执行 time past 00:00:00.0156250

华丽!太华丽了! 你不觉得么 ?当10万次的时候直接出来一个0 所以我调整到了100万次,你是否感觉到了什么 ?

是否有“啊哈!”这样的感觉? 那么一丝的,一点点的曙光?

是的,至少我感觉到了,今天的测试就到这里,希望大家喜欢,下一篇也许我会为你点亮那片黑暗。

希望大家喜欢:)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值