自制DynamicProxy开发成功,性能测试提升了1.4倍。(看来微软的realproxy并不弱!导致我无法提升一个数量级)


参考了微软的realproxy设计模式,使用相同的IMessage结构,重写了整个proxy。

使用了emit技术,性能得到了极大提升。

模仿旧的pojo代码,得到: 

代码
    class MyProxy<T> : DynamicProxy
    {
        Dictionary
<stringobject> dict = new Dictionary<stringobject>();

        
public MyProxy()
            : 
base(typeof(T))
        {
        }

        
public T Value
        {
            
get
            {
                
return (T)base.GetTransparentProxy();
            }
        }

        
public override IDynamicMethodReturnMessage Invoke(IDynamicMethodCallMessage msg)
        {
            
string methodname = msg.MethodInfo.Name.Trim().ToUpper();

            
if (methodname.StartsWith("GET_"))
                
return InvokeGetter(msg);

            
if (methodname.StartsWith("SET_"))
                
return InvokeSetter(msg);

            
return base.CreateReturnMessage(new Exception("only support property."), msg);
        }

        
private IDynamicMethodReturnMessage InvokeGetter(IDynamicMethodCallMessage methodCall)
        {
            IDummyMethodInfo method 
= methodCall.MethodInfo;

            
string invokeid = GetInvokeMessageId(method);

            
if (dict.ContainsKey(invokeid))
            {
                
return base.CreateReturnMessage(dict[invokeid], methodCall);
            }

            
if (method.ReturnType.PropertyType == DotNetPropertyType.Enum)
            {
                
return base.CreateReturnMessage(0, methodCall);
            }

            
switch (Pixysoft.Tools.ParserHelper.GetDataTypeByTypeName(method.ReturnType.Name))
            {
                
case DotNetDataType.Boolean:
                    {
                        
return base.CreateReturnMessage(false, methodCall);
                    }

                
case DotNetDataType.Byte:
                    {
                        
return base.CreateReturnMessage(byte.MinValue, methodCall);
                    }

                
case DotNetDataType.Char:
                    {
                        
return base.CreateReturnMessage(char.MinValue, methodCall);
                    }

                
case DotNetDataType.DateTime:
                    {
                        
return base.CreateReturnMessage(DateTime.MinValue, methodCall);
                    }

                
case DotNetDataType.Decimal:
                    {
                        
return base.CreateReturnMessage(decimal.MinValue, methodCall);
                    }
                
case DotNetDataType.Double:
                    {
                        
return base.CreateReturnMessage(double.MinValue, methodCall);
                    }
                
case DotNetDataType.Int32:
                    {
                        
return base.CreateReturnMessage(int.MinValue, methodCall);
                    }
                
case DotNetDataType.Int64:
                    {
                        
return base.CreateReturnMessage(Int32.MinValue, methodCall);
                    }
                
case DotNetDataType.Single:
                    {
                        
return base.CreateReturnMessage(Single.MinValue, methodCall);
                    }
                
case DotNetDataType.String:
                
case DotNetDataType.UNKNOWN:
                
default:
                    {
                        
return base.CreateReturnMessage(null, methodCall);
                    }
            }

        }

        
private IDynamicMethodReturnMessage InvokeSetter(IDynamicMethodCallMessage methodCall)
        {
            
if (methodCall.InArgCount == 0)
                
return base.CreateReturnMessage(null, methodCall);

            
string invokeid = GetInvokeMessageId(methodCall.MethodInfo);

            
if (dict.ContainsKey(invokeid))
                dict.Remove(invokeid);

            dict.Add(invokeid, methodCall.InArgs[
0]);

            
return base.CreateReturnMessage(null, methodCall);
        }

        
private string GetInvokeMessageId(IDummyMethodInfo method)
        {
            StringBuilder builder 
= new StringBuilder();
            builder.Append(method.Name.Substring(
4));
            builder.Append(method.DeclaringType.FullName);
            
//return builder.ToString();
            return Pixysoft.Security.MD5.GetMD5(builder.ToString());
        }
    }

    
public interface IproxyWithProperty
    {
        
string Name { set;get;}
    }

测试代码如下: 

代码
        //performance
        public void test002()
        {
            IproxyWithProperty pojo 
= Pixysoft.Tools.PojoHelper.GetPojo<IproxyWithProperty>();

            IproxyWithProperty proxy 
= new MyProxy<IproxyWithProperty>().Value;

            Pixysoft.Tools.CodeTimer.Initialize();

            Pixysoft.Tools.CodeTimer.Time(
"pojo"100000delegate()
            {
                pojo.Name 
= "123";
                
object name = pojo.Name;
            });


            Pixysoft.Tools.CodeTimer.Time(
"proxy"100000delegate()
            {
                proxy.Name 
= "123";
                
object name = proxy.Name;
            });
        }

测试结果如下:

------ Test started: Assembly: Pixysoft.Framework.Reflection.dll ------


pojo

Time Elapsed: 7,997ms

CPU time: 7,796,875,000ns

Gen 0: 760

Gen 1: 0

Gen 2: 0


proxy

Time Elapsed: 5,651ms

CPU time: 5,484,375,000ns

Gen 0: 398

Gen 1: 0

Gen 2: 0



1 passed, 0 failed, 0 skipped, took 13.77 seconds (Ad hoc).


性能提高了1.415倍。

如果把初始化proxy的代码放入循环,得到结果:

------ Test started: Assembly: Pixysoft.Framework.Reflection.dll ------


pojo

Time Elapsed: 8,569ms

CPU time: 8,015,625,000ns

Gen 0: 800

Gen 1: 0

Gen 2: 0


proxy

Time Elapsed: 6,263ms

CPU time: 5,843,750,000ns

Gen 0: 475

Gen 1: 0

Gen 2: 0


性能提高了1.368倍。

可以看出,微软的Realproxy本质上并不弱。 内部实现应该使用了类似emit的技术了。。。

因此,一天的努力几乎有点白费了。。。竟然没有提高一个数量级。。。


1 passed, 0 failed, 0 skipped, took 14.92 seconds (Ad hoc).


原文地址:https://www.cnblogs.com/zc22/p/1751974.html