最近文章更新
- 1966年生产的广州 珠江 SB6-2型 ..
- HD6870/6850全面评测,让你大饱眼..
- 百万现金刚入门 中国7大奢华私人..
- 罕见4G希捷酷鱼系类万转SCSI服务..
- IBM 6x86MX PR333 CPU
- 采用MC68000 CPU的进口老计算机主..
- 1989年IBM-XT机软驱
- BC3型饱和标准电池拆解
- JUKO ST
- Kingston 品牌的CPU
- YAMAHA 719
- intel 30线 内存条
- intel mmx cpu和主板
- 首款xHCI 1.0正式版标准USB 3.0控..
- 《极品飞车:地下狂飙》纹理MOD视..
- USB接口加扩展子卡:影驰神秘GTX..
- 阿里巴巴将发布浏览器 核心不是W..
- 黄仁勋大秀NVIDIA LOGO纹身
- Google Earth上的奇特卫星图片
- 开火!讯景限量版HD 5970详细测试..
相关文章链接
最新新闻资讯
本周下载排行
- ArcSoft TotalMedia Theatre 3 P..
- Windows 7 Build 7600 16385 RTM..
- 《姗姗来迟软件光盘+飞扬PE工具箱..
- MSDN Windows 7 RTL 7600 Ultima..
- Windows 7 Home Premium (x86) -..
- Windows Virtual PC (x86) - (Mu..
- MSDN Windows 7 Language Pack X..
- Windows 7 Language Pack (x64) ..
- Windows 7 Starter (x86) - DVD ..
- Windows 7 Professional (x86) -..
- Windows 7 Language Pack (x86) ..
- Windows 7 Home Premium (x64) -..
- Windows XP Mode (x86, x64) - (..
- 7127.0.090507-1820_x86fre_clie..
- DMG2ISO
本月下载排行
- ArcSoft TotalMedia Theatre 3 P..
- Windows 7 Build 7600 16385 RTM..
- 《姗姗来迟软件光盘+飞扬PE工具箱..
- MSDN Windows 7 RTL 7600 Ultima..
- MSDN Windows 7 Language Pack X..
- Windows 7 Home Premium (x86) -..
- Windows 7 Language Pack (x64) ..
- Windows 7 Professional (x86) -..
- 7127.0.090507-1820_x86fre_clie..
- Windows 7 Professional (x64) -..
- Windows 7 Starter (x86) - DVD ..
- Windows Virtual PC (x86) - (Mu..
- Windows 7 Ultimate (x64) - DVD..
- Lenovo Windows 7 Ultimate OEM ..
- Windows 7 Home Premium (x64) -..
- 阅览次数: 文章来源: 原文作者: 整理日期: 2010-08-29
拓展动态编程的新领域
拓展动态编程的新领域
中文MSDN将CallSite<T>译为“动态(调用)站点”,它是DLR中的核心组件之一。
动态站点对象通过CallSite<T>.Create()方法创建, C#编译器会为其指定一个派生自CallSiteBinder的对象(称为“动态站点绑定对象”)作为其参数。
动态站点绑定对象是与具体语言相关的,比如IronPython和C#都有各自的动态站点绑定对象。
动态站点绑定对象的主要工作是将代码中的动态表达式(本例中为d++)转换为一棵“抽象语法树(AST:Abstract Syntax Tree)”,这棵语法树被称为“DLR Tree”,是在.NET 3.5所引入的LINQ表达式树的基础上扩充而来的,因此,有时又称其为“表达式树(Expression Tree)”
DLR在内部调用此表达式树的Compile()方法生成IL指令,得到一个可以被CLR所执行的委托(在本例中其类型就是Func<CallSite, object, object>)。
动态调用站点对象(本例中为<>p__Site1)有一个Target属性,它负责引用这一生成好的委托。
委托生成之后,动态表达式的执行就体现为委托的执行,其实参由C#编译器直接“写死”在IL代码中。
简化的代码示意如下(通过Reflector得到,为便于阅读,修改了变量名):
object d = 100; object CS$0$0000 = d; if (<>p__Site1 == null) <>p__Site1 = CallSite<Func<CallSite, object, object>>.Create(……); d = <>p__Site1.Target(<>p__Site1, CS$0$0000); |
上述类型推断、方法绑定及IL代码生成的工作都是在程序运行时完成的。
(4)动态代码很慢吗?
动态编程语言易学易用,代码紧凑,开发灵活,但性能则一直是它的“软肋”。为了提升性能,DLR设计了一个三级缓存策略。
动态站点绑定对象会为动态调用表达式转换而成的语法树加上相应的测试条件(称为“test”),构成一个“规则(Rule)”,这个规则可以用于判断某个语法树是否可用于特定的动态调用表达式。
举个例子,请看以下这个动态表达式:
d1 + d2 |
如果在程序运行时d1和d2都是int类型的整数,则DLR生成的规则为:
if( d1 is int && d2 is int) //测试条件 return (int)d1+(int)d2; //语法树 |
DLR通过检查规则中的“测试条件”,就可以知道某个动态表达式是否可以使用此规则所包容的语法树。
“规则”是DLR缓存的主要对象。
前面介绍过的动态站点对象Target属性所引用的委托是第一级缓存,它实现的处理逻辑是这样的:
//当前处理规则,属于第1级缓存 if( d1 is int && d2 is int) //测试条件 return (int)d1+(int)d2; //满足测试条件,直接返回一个表达式树 //未命中,则在第2级、第3级缓存中查找,如果找到了,用找到的结果更新第1级缓存 return site.Update(site,d1,d2); |
如果3级缓存中都没有命中的规则,则此动态站点所关联的调用站点绑定对象会尝试创建一个新的规则。如果创建新规则失败,则由当前编程语言(比如C#)所提供的默认调用站点绑定对象决定如何处理,通常的作法是抛出一个异常。
当前版本的DLR第2级缓存了10条规则,第3级则缓存了100条规则。
由于DLR自身设计了一个“规则”缓存系统,又充分利用了CLR所提供的JIT缓存(因为所有动态调用代码最终都会转换为CLR可以执行的IL指令,而CLR可以缓存这些代码),使得动态代码仅仅在第一次执行时性能较差,后续的连续调用其性能可以逼近静态代码。