00:00
欢迎每个戴先生,出事听不懂算我的。哥哥姐姐们好,我是小灵儿,今天由我来开场哦,你们知道吗?编程员有好多好多哦,连10个手指头都数不完呢,那他们到底有什么不一样呀?其实呢,所有的编程语言都在走同一条小路哦,不一样的地方就是怎么走完这条小路了。接下来教给我老爸在街上了,哎哟,开的不错哦。说白了,这是一场关于控制权的拉扯。今天咱们就从性能与内存安全的维度看看几门主流语言是怎么各走各路的。先从极致性能型说起,先得个脚,并非说这类语言是为了追求性能而生的,性能只是因为把控制权交给程序员后现在产生的好处。性能能爬多高,主要还得看程序员能不能把这份控制权用到位。这类语言的代表选手就是CC加加,它的路线最直接,没有中间商赚差价。
01:05
不过严格说也不算零中间商了,用户程序里其实还链接着一个辅助型乱站,它是程序的真正入口,程序启动时有它,先干点初始货的活,干完再就用你的may函数,等你没跑完,嗯,等你may函数跑完退场,它再回来收尾,所以他就是迎宾云那种角色,不去插手正式。也就是说乱time不结管你的逻辑,那内存安全谁来保证呢?这就是代价了。辅助型乱颤只管开门关门,不会去管你的物里怎么闹,所以你写崩了他也不拦着。再一个讲,这类语言的初衷不只是内存安全,但内存安全确实是引入接管,是乱看后因收回部分控制权而得到的核心好处之一。那想用内存安全咋办?计换机界有句名言,没有什么是加一层搞不定的,那我们就在中间加一层专门的接管层,让。
02:05
他来处理底层这些麻烦事就是个不错的思路,那就得请接管型乱time出马了,他就像个微型操作系统,用户程序只是它的一个任务,需要借助它来运行,所以路线就变成。接下来咱们分三代来看,一个一个聊。注意这里的代不是按语言出现的时间先后顺序,而是按设计思路的眼镜来分的。初代的代表选手是javascript。路线如下,源码在运行时直接交给runtime程序运行的时候,Runtime, 比如V8引擎会先读一遍字符串,源码怎么读?就是把源码pass成AST,再根据AST生成字解码,之后就解释执行这些字解码了。这里头名词挺多的。首先什么是AST AST就是抽象语法数字符串源码里的语法结构是隐。
03:05
行的计算机难以直接处理,所以得把它解析成一棵树,层次和嵌套关系就一目了然的。比如A+B×2这行代码对应的AST大概长这样,那有了AST,计算机就可以处理了。为什么还要自解码呢?因为如果没有自检码,直接根据AST来执行,那每次执行都得重新立规,便利测个数,开销很大。所以会在首次执行之前先把ST遍历一遍,拍平成一组线性的指令序列,这就是自解码之后执行时直接按顺序读取指令即可,不用再碰AST了。还是拿上面的A+B×2的例子来说,拍平后大概长这样,这样肯定会快很多。那解释执行呢?也没有人还分不清编译和解释的区别,解释就是run。
04:05
早就为每种字解码指令写好了对应的实现,字解码只是一份数据,一份描述行为的数据。解释器逐条读取字解码,根据指令类型执行对应的代码,这不就是D码DSL的实现思路吗?至于编译,可以不严谨的理解为把A翻译成B。比如把源码翻译成字解码的过程,是不是感觉runtime在处理代码上做的事有点多?那是因为它在程序运行的时候把代码编译的事给做了。第二代的改进在于编译时机,在把代码数据给到乱探之前会提前处理,就是把源码编译成字解码。路线图如下,代表选手就是Java,他会先把Java字符串源码编译成中间表示,也就是二进制的字解码,在程序运行时,J vm runtime直接解释执行。
05:05
切自解码就可以了。与初代的比较,我们可以打个比方,初代就像是现场读菜谱做菜,而第二代就是提前把菜谱整理成标准工序,做起来当然快了。第三代的路线演变成上面字样了,直接把源码编译成机器码,跟乱探秘奇打包能够就是这类的代表选手,跟CC加比就多了个乱探源码,但用户程序仍然只是乱探,这个微型操作系统的任务需要通过乱探来调度。那有个问题,既然用户程序最终也编译成了机器码,可以直接CPU执行,乱探是怎么干涉的呢?简单讲,首先程序的入口依然是乱探,不是你的妹,所以调度天然被接管。其次是在编译期做手脚,把特定的代码替换成runtime,内部函数的调用是不是跟你想的一样?
06:05
发展到自带性能已经极限了吧?因为这里不再有自解码解释,开销全都是CPU直接执行机器码,但接管型乱颤依然存在,对性能仍有影响。手是不是就没有两全其美的方案吗?还真有,Ru就是这类的代表选手,它的路线如下,这不又要又回到原点了吗?表面看是一样,但人家性能也要,内存安全也要,它像CC加加一样,直接把源码编译成机器码,CPU可以直接执行,那它又是怎么做到内存安全的?不是说没有接管型乱time的吗?这就是lost的骚操作了,这个操作嘛,咱们下次再聊,我要去吃饭了,拜拜。
我来说两句