什么是编译语言什么是解释
![](https://i-blog.csdnimg.cn/blog_migrate/6c9b7582b53a0fc2a2a1a1718d325341.png)
CPU只讲一种语言。 他们不在乎你用什么语言写
程序员往往会对已编译语言和解释语言之间的假定差异进行大量处理。 还是动态语言与静态类型的语言。
传统的观点是这样的:编译的语言存储在机器代码中,并且由CPU无延迟执行,一次将解释的语言转换为机器语言一条指令,这使其运行缓慢。 动态语言的速度较慢,这是因为在运行时找出类型会产生开销。
现实并非如此
很久很久以前,当程序员向裸机写信并且编译器不那么老练时,这种简单化的观点可能有些正确。 但是,有两点使今天的事实显然是错误的。
首先,当今所有流行的编程语言(Java,JavaScript,Python,Scala,Kotlin,.NET和Ruby)都在虚拟机上运行。 虚拟机本身以多种语言编写*。
第二件事是,VM使查看程序的执行变得更加容易,这反过来又使得JIT(及时)编译成为可能。
那么,一个真实的示例说明了为什么如此重要:Java。
Java已编译。 还是? 好吧……不是真的。 是的,有一个编译器可以使用您的源代码并创建Java字节码,但是您知道该字节码后,JVM会使用该字节码做什么吗?
首先,它会建立一棵树。 它反汇编 Java字节码并构建语义树,以便它可以弄清楚源代码试图做什么。 为了做到这一点,它必须撤消编译器已经仔细考虑的所有令人讨厌的优化。 它会丢弃编译后的代码。
听起来很疯狂! 那么为什么要这样做呢? 该问题的答案是理解本文标题的关键。
理解代码的最佳方法是观看代码的运行情况
这适用于人类,但也适用于编译器。 现代JVM取消编译和优化的原因是“常规”编译的Java字节码在JVM上运行得太慢 。 为了获得近来Java众所周知的执行速度,JIT必须丢弃静态编译(和静态优化)的代码,并“监视” JVM中运行的代码,并根据代码的实际行为进行优化。在运行时**。
不要绕着说“ [[ 在此处插入语言名称 ]太慢,因为它被解释了”之类的事情,因为这根本不是事实。 语言只是语法,可以有许多实现(例如,有几种Java实现)。 您可能会说“ [[ 在此处插入语言名称 ]很慢,因为解释器/ VM没有JIT”,这可能是正确的。
语言不快也不慢
C ++不是更快的语言。 C ++的运行速度之快,仅仅是因为在编译器优化上花费了比其他任何语言更多的时间,因此它们当然更好。 值得注意的是,使用PGC ++和Clang编译的程序通常比使用AOCC编译器编译的相同源代码快2到3倍。 这证明了编译器及其优化(而不是语言本身)会严重影响执行性能。
通常认为Java是第二快的,这是因为它在JIT编译器上投入的时间超过了除C / C ++之外的任何时间。
框架或语言还原
但这并不完全取决于编译器。 我已经写过关于未经审查的库和框架的危险。 该文章也可能标题为“ 语法或库”:您知道使用的是哪一种吗? 我请一个值得信赖的朋友审阅这篇文章,并提出一个很好的观点,即内存访问模式是整体性能的大元凶。 他指出C程序受益于以下事实:
“ C仅具有基本数组和结构(但是它非常自由地使用了指针,因此您可以足够耐心地将任何东西纠缠到这些基本结构中)。 使用哈希图或树可能会非常痛苦,因此请避免使用它们。 这样做的好处是使您略过有效利用内存和缓存的数据布局。 也没有闭包和动态创建的函数,因此您的代码和数据大部分保留在内存中可预测的位置。
然后再看Ruby之类的语言,它的语言设计鼓励最大的活力。 一切都倾向于在哈希表查找之后,甚至在对象上调用固定不变的方法(因为自从您上次调用该方法以来,有人可能已经用另一种方法替换了该方法)。 任何东西都可以移动或包裹在另一个匿名闭包中。 这会创建内存访问模式,其中散布着遍布整个地方的小对象的“马赛克”,代码花了很多时间从内存中寻找每个难题,然后指向下一个难题。
简而言之,C鼓励非常可预测的内存布局,而Ruby鼓励非常不可预测的内存布局。 一个优化的编译器不能解决这个问题。 ”
我必须同意。 这就使我清楚地表达了我的观点:不了解语法在哪里停止和库在哪里开始的程序员注定要编写他们不真正理解其执行的程序。
我相信写一个真正糟糕的C程序会比较困难,因为(如果它完全运行的话)要手动重现Ruby随便产生的内存混乱将是太多的工作。
然后,我们就某个大型高科技公司如何创建“清理过PHP ++”进行了有趣的交谈。 他有一些有趣的话要说,也许他会写一篇有关它的文章。
谢谢您的帮助Pauli 。
因此,我争论的一个隐含部分是,现代编程语言降低了门槛,因此许多程序员不会考虑基本的计算机科学(内存结构和计算复杂性),因此没有依据来理解其程序将如何执行。
我争论的另一部分是,从纯语法角度考虑,任何图灵完整的语言都可以像其他任何语言一样快地运行。 例如,我相信绝对可以在JVM上创建高性能的Ruby实现。 我很容易承认,大多数当前的Ruby代码都会在该系统上崩溃,但这是由于标准库中进行了编程选择,而不是语言(语法)本身的基本约束。
我已经说过,(作为一个自认的货运邪教程序员)我绝对有可能不了解Ruby语法和/或Church-Turing论文 。
CPU(或VM)仅讲一种语言
尽管有Ruby及其内存管理的散弹枪方法; 任何在Java和C上花费大量时间来优化其编译的编程语言,其运行速度都将与Java或C一样快,这是因为CPU(和VM)仅讲一种语言: 机器语言 。 无论您使用哪种语言编写, 迟早都会将其编译成机器语言 ,而影响性能的是标准库中如何实现基本的计算机科学原理,以及编译的有效性 , 而不是何时发生。
这个故事的寓意是,程序员应该花更少的时间来研究语言,而应该花更多的时间来了解他们的幕后工作方式。
最后,我引用伟大的苏斯曼的话:
“……计算机永远不会足够大或不够快。 硬件技术的每一次突破都会导致更多的编程企业,新的组织原则以及丰富的抽象模型。 每个读者都应该定期问自己“走向何方,走向何方?”,但不要经常问自己,以免您忘却了苦乐参半的便秘编程的乐趣。
*原始的Sun JVM用C编写。原始的IBM JVM用SmallTalk编写。 其他JVM已使用C ++编写。
Java API(大多数Java程序员无法使用它们编写的类库,即使是简单的应用程序)大部分都是用Java本身编写的。
** 值得注意的是,当VM的机器语言“命中”硬件CPU时,会再次发生这种情况,硬件CPU立即获取一组指令,将其分解,寻找可以优化的模式,然后重新构建它们,以便进行处理。可以管道微码。
翻译自: https://hackernoon.com/interpreted-compiled-what-ever-7edebf774ed1
什么是编译语言什么是解释