• 为什么托管代码要慢


    以前只知道托管语言比非托管语言慢,具体为什么慢 、慢在哪里 、还有就是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时间。好在微软进行了大量的性能优化工作,将这些额外的开销保持在最低限度之内。

  • 相关阅读:
    10 行Python代码实现批量压缩图片500 张,面试必学
    用Python邮件发送,新手必学
    用Python监控男女朋友每天都在看哪些网站?这招绝了
    不踩坑的Python爬虫:如何在一个月内学会爬取大规模数据?新手必学
    用Python做一个520表白神器,值得收藏
    微分不等式
    零点问题
    2019英语一 Text4分析
    A1065. A+B and C(64bit)
    A1046. Shortest Distance
  • 原文地址:https://www.cnblogs.com/xiaopotian/p/5102208.html
Copyright © 2020-2023  润新知