玩转动态编译:三、提高性能,抛弃反射
2013-08-09 07:53
183 查看
玩转动态编译:一、初识
玩转动态编译:二、实战
通过之前2篇文章的介绍,大家一定发现了,动态编译后的对象只能通过反射调用,但是反射往往是一个程序性能的瓶颈,这个真的无法突破么?答案当然是否定的,接下来就我就来说说怎么才能,挖掘动态编译的潜力。
一点废话
我刚来博客园才1星期左右,昨天才弄懂怎么发表到首页,先说声抱歉了,昨天的文章有几个地方贴的源码居然少了几个字符,有点莫名其妙,也难怪有人不能运行了,虽然是小错误,但是如果认真检查的话也是可以避免的,这是我的失误。
还有一点,这个《玩转动态编译》是一个系列的,虽然没有大纲,不知道会写到几,但是内容一定是循序渐进的,所以如果你看到了不合理的地方,请不要惊讶,可能我只是为了更好理解,也许下一篇就会把这个地方重构的。
回复上一篇中的博友 飘的移
引用我只想:说这个效率实在太慢了,楼主什么时候能做到接近FastJson或者Newton.Json的速度就牛叉了
FastJson是Java的,我测试不了,但就Newtonsoft.Json的效率来说超过他还是可以的,所以在这个系列没有over之前耐心期待吧。。。。(这个算广告吗)
[b]书归正传,话转正题[/b]
通过之前2篇文章的介绍,大家一定发现了,动态编译后的对象只能通过反射调用,但是反射往往是一个程序性能的瓶颈,这个真的无法突破么?答案当然是否定的。
那怎么才能抛弃反射呢?
仔细看之前的《玩转动态编译》大家可以发现,之前2个栗子编译的都是静态方法。
回到昨天的栗子中,被静态编译的User解析类
ps:其实回车都是我刚刚加上去的,难道我会乱说?
编译静态的方法,只是为了在反射调用Invoke的时候不要传入实例对象,就像这样
程序中,我们可以缓存最后的met对象,可以防止反复的编译。不过就算是这样,每次调用met对象的时候依然是反射调用(Invoke)
是静态方法的话就意味着必须要使用反射,静态只能通过 类名.方法名 来调用,而动态编译的类名是在程序运行时决定的。。。。
思考?
那么是否意味着实例方法就可以呢?
把上面的动态代码改一下
看有那些地方改变?
1,实现了IGetString的接口
View Code
所以还是那句话,期待吧~
玩转动态编译:二、实战
通过之前2篇文章的介绍,大家一定发现了,动态编译后的对象只能通过反射调用,但是反射往往是一个程序性能的瓶颈,这个真的无法突破么?答案当然是否定的,接下来就我就来说说怎么才能,挖掘动态编译的潜力。
一点废话
我刚来博客园才1星期左右,昨天才弄懂怎么发表到首页,先说声抱歉了,昨天的文章有几个地方贴的源码居然少了几个字符,有点莫名其妙,也难怪有人不能运行了,虽然是小错误,但是如果认真检查的话也是可以避免的,这是我的失误。
还有一点,这个《玩转动态编译》是一个系列的,虽然没有大纲,不知道会写到几,但是内容一定是循序渐进的,所以如果你看到了不合理的地方,请不要惊讶,可能我只是为了更好理解,也许下一篇就会把这个地方重构的。
回复上一篇中的博友 飘的移
引用我只想:说这个效率实在太慢了,楼主什么时候能做到接近FastJson或者Newton.Json的速度就牛叉了
FastJson是Java的,我测试不了,但就Newtonsoft.Json的效率来说超过他还是可以的,所以在这个系列没有over之前耐心期待吧。。。。(这个算广告吗)
[b]书归正传,话转正题[/b]
通过之前2篇文章的介绍,大家一定发现了,动态编译后的对象只能通过反射调用,但是反射往往是一个程序性能的瓶颈,这个真的无法突破么?答案当然是否定的。
那怎么才能抛弃反射呢?
仔细看之前的《玩转动态编译》大家可以发现,之前2个栗子编译的都是静态方法。
回到昨天的栗子中,被静态编译的User解析类
using blqw; using System; using System.Collections; using System.Text; public class _336090f4e7724d2585b07e79210decb4 { public static string a(User obj) { return new StringBuilder().Append("{\"UID\":") .Append(Json.Converter2.FromGuid((System.Guid)obj.UID)) .Append(",\"Name\":") .Append(Json.Converter2.FromString((System.String)obj.Name)) .Append(",\"Birthday\":") .Append(Json.Converter2.FromDateTime((System.DateTime)obj.Birthday)) .Append(",\"Sex\":") .Append(Json.Converter2.FromEnum((Enum)obj.Sex)) .Append(",\"IsDeleted\":") .Append(Json.Converter2.FromBoolean((System.Boolean)obj.IsDeleted)) .Append(",\"LoginHistory\":") .Append(Json.Converter2.FromArray(((IEnumerable)obj.LoginHistory).GetEnumerator())) .Append(",\"Info\":") .Append(Json.ToJson_2(obj.Info)) .Append("}").ToString(); } }
ps:其实回车都是我刚刚加上去的,难道我会乱说?
编译静态的方法,只是为了在反射调用Invoke的时候不要传入实例对象,就像这样
var code = CreateCode(type);//获得代码 var ass = DynamicCompile_1.CompileAssembly(code, typeof(Json), typeof(StringBuilder), typeof(IDictionary), typeof(Enum), typeof(IEnumerable), typeof(IEnumerator));//编译 var met = ass.GetTypes()[0].GetMethods()[0];//反射唯一的一个对象中的唯一的一个方法 return (string)met.Invoke(null, new object[] { user });//执行方法,等到返回值
程序中,我们可以缓存最后的met对象,可以防止反复的编译。不过就算是这样,每次调用met对象的时候依然是反射调用(Invoke)
是静态方法的话就意味着必须要使用反射,静态只能通过 类名.方法名 来调用,而动态编译的类名是在程序运行时决定的。。。。
思考?
那么是否意味着实例方法就可以呢?
把上面的动态代码改一下
using blqw; using System; using System.Collections; using System.Text; public class _336090f4e7724d2585b07e79210decb4 : blqw.IGetString { public string GetString(object o) { User obj = (User)o; return new StringBuilder().Append("{\"UID\":") .Append(Json.Converter2.FromGuid((System.Guid)obj.UID)) .Append(",\"Name\":") .Append(Json.Converter2.FromString((System.String)obj.Name)) .Append(",\"Birthday\":") .Append(Json.Converter2.FromDateTime((System.DateTime)obj.Birthday)) .Append(",\"Sex\":") .Append(Json.Converter2.FromEnum((System.Enum)obj.Sex)) .Append(",\"IsDeleted\":") .Append(Json.Converter2.FromBoolean((System.Boolean)obj.IsDeleted)) .Append(",\"LoginHistory\":") .Append(Json.Converter2.FromArray(((IEnumerable)obj.LoginHistory).GetEnumerator())) .Append(",\"Info\":") .Append(Json.ToJson_2(obj.Info)) .Append("}").ToString(); } }
看有那些地方改变?
1,实现了IGetString的接口
纯反射 每次10000 共10次 168ms | 153ms | 152ms | 152ms | 154ms | 157ms | 157ms | 158ms | 158ms | 153ms | 动态编译 每次10000 共10次 222ms | 116ms | 118ms | 117ms | 113ms | 109ms | 105ms | 106ms | 105ms | 107ms | Newtonsoft.Json 每次10000 共10次 359ms | 177ms | 192ms | 182ms | 188ms | 189ms | 189ms | 189ms | 187ms | 189ms | ====纯反射==== {"UID":"1e10fe905f7d41d0bda2210abcb12349","Name":"blqw","Birthday":"1986-10-29 1 8:00:00","Sex":"Male","IsDeleted":false,"LoginHistory":["2013-08-09 08:00:00","2 013-08-09 10:10:10","2013-08-09 12:33:56","2013-08-09 17:25:18","2013-08-09 23:0 6:59"],"Info":{"Address":"广东省广州市","Phone":{"手机":"18688888888","电话":"82 580000","短号":"10086","QQ":"21979018"},"ZipCode":510000}} ====动态编译==== {"UID":"1e10fe905f7d41d0bda2210abcb12349","Name":"blqw","Birthday":"1986-10-29 1 8:00:00","Sex":"Male","IsDeleted":false,"LoginHistory":["2013-08-09 08:00:00","2 013-08-09 10:10:10","2013-08-09 12:33:56","2013-08-09 17:25:18","2013-08-09 23:0 6:59"],"Info":{"Address":"广东省广州市","Phone":{"手机":"18688888888","电话":"82 580000","短号":"10086","QQ":"21979018"},"ZipCode":510000}} ====Newtonsoft.Json==== {"UID":"1e10fe90-5f7d-41d0-bda2-210abcb12349","Name":"blqw","Birthday":"\/Date(5 30964000000+0800)\/","Sex":0,"IsDeleted":false,"LoginHistory":["\/Date(137600640 0000+0800)\/","\/Date(1376014210000+0800)\/","\/Date(1376022836000+0800)\/","\/D ate(1376040318000+0800)\/","\/Date(1376060819000+0800)\/"],"Info":{"Address":"广 东省广州市","Phone":{"手机":"18688888888","电话":"82580000","短号":"10086","QQ": "21979018"},"ZipCode":510000}}
View Code
所以还是那句话,期待吧~
相关文章推荐
- 提高性能,抛弃反射
- 【jquery仿dataList——性能优化】模板预编译思想提高性能10倍以上!!!
- [ZT]使用DynamicMethod替代反射,提高100倍的性能!(附源码)
- EF Core 使用编译查询提高性能
- .NET Core/Framework 创建委托以大幅度提高反射调用的性能
- .NET Core/Framework如何创建委托大幅度提高反射调用的性能详解
- [Golang语言社区]--提高 golang 的反射性能
- 动态编译_DynamicCompile、反射调用main方法问题JAVA214
- AWE GAE MEGOO 和 提高性能的INTEL的C++重新编译 BigTable是什么东东
- 基础笔记13(动态性:反射,动态编译,执行,操作)
- 用动态生成的委托提高调用动态程序集的性能
- 动态编译Java并通过反射执行方法
- 使用dynamic来简化反射实现,并且提高了性能
- 动态编译与性能测量--动态编译情况下指标评测的风险
- 使用 WebSphere Application Server V8.5 的动态集群功能提高资源利用率并改善性能
- 分享Web应用运行的细节问题:预编译提高网站性能、跟踪用户习惯和解决线程同步
- 玩转动态编译 - 高级篇:一,IL访问静态属性和字段
- 关于动态创建控件性能提高 以及 SuspendLayout & ResumeLayout 的使用
- C# 动态编译及反射执行
- 玩转动态编译:一、初识