zoukankan      html  css  js  c++  java
  • 为什么托管代码要慢

    以前只知道托管语言比非托管语言慢,具体为什么慢 、慢在哪里 、还有就是web部署以后为什么第一次打开总是很慢了解的一知半解,最近看了CLR via C#后总算了解了。

     Main方法执行之前CLR会对检测出Main代码引用的所有类型,并分配一个内部数据结构来管理对引用类型的数据访问。如图Main方法引用一个Console类型,导致CLR分配一个内部结构。在这个内部结构当中,Console类型定义的每个方法都有一个对应的记录项。每个记录项含有一个地址,根据地址即可找到方法的实现。对这个结构初始化时,CLR将每个记录项都设置成(指向)包含在CLR内部的一个未编档函数。称之为JITCompiler。Main方法首次调用WriteLine时,JITCompiler函数都会被调用。JITCompiler函数负责将方法的IL编译成本机的CPU指令。由于IL是“即时”(just in time)编译的,所以通常将CLR的这个组件成为JITter或者JIT编译器。

    好吧,以上是JIT编译器的定义,敲得好心累,不过敲一遍确实有助于理解。

    JITCompiler会在定义程序集的元数据当中查找被调用方法的IL,然后验证IL代码,并将IL代码编译成本机CPU指令。本机CPu指令保存到动态分配的内存当中。然后JITCompiler回到CLR为类型创建的内部数据结构,找到与被调用方法对应的那条记录,修改最初对JITCompiler的引用,使其指向内存块的地址。

    JITCompiler函数跳转到内存块中的代码,这些代码正是WriteLine方法的具体实现。

    代码执行并返回继续执行。

    第二次调用WriteLine,会直接执行内存中的代码块,完全跳过JITCompiler函数。

    所以说方法仅在第一次调用时才会有性能损失,以后对该方法的调用都是以本机代码德兴市全速运行,无需重新验证IL并编译成本机代码。但是程序一旦终止,编译好的代码也会被丢弃。

    非托管代码是针对一种具体CPU平台编译,一旦调用,代码就能直接执行。但在现在这种托管环境中,代码的编译分两个阶段进行。首先,编译器遍历源代码,做大量工作生成IL代码,但正正想要执行,这些IL代码必须在运行时编译成本机CPU指令,这需要分配更多的非共享内存,病要花费额外的CPU时间。好在微软进行了大量的性能优化工作,将这些额外的开销保持在最低限度之内。

  • 相关阅读:
    增量更新代码步骤记录
    软件缺陷管理基本流程
    数据库语言(三):MySQL、PostgreSQL、JDBC
    eclipse的使用
    数据库语言(二):SQL语法实例整理
    windows下MySql没有setup.exe时的安装方法
    数学:完全独立于实际场景的情况下定义的概念,可以正确的描述世界
    数学语言和程序语言的对比:面向过程与面向集合&命题
    iOS开发之IMP和SEL(方法和类的反射)
    iOS之UIButton的normal和selected状态切换
  • 原文地址:https://www.cnblogs.com/xiaopotian/p/5102208.html
Copyright © 2011-2022 走看看