如果没有DOM,静态类型,提前编译的javascript代码与本机代码性能相比如何?

时间:2013-05-04 16:28:51

标签: javascript performance compilation native jit

“为什么Javascript比本机代码慢?”的传统答案。是:“因为它被解释”。这种说法的问题在于解释不是语言本身的质量。事实上,现在大多数Javascript代码都被JIT,但是,它甚至还没有接近本机速度。

如果我们从等式中删除解释因子并编译Javascript AOT怎么办?它会匹配本机代码的性能吗?如果是的话,为什么这不是通过网络*广泛完成的?如果不是,现在性能瓶颈在哪里?

如果新的瓶颈是DOM,那么如果我们也消除它呢?一个没有DOM,编译的Javascript会像本机代码一样高效吗?如果是的话,为什么不通过网络广泛宣传**?如果不是,现在性能瓶颈在哪里?

在剥离DOM部分和解释部分之后,我在Javascript和C / C ++之间看到的唯一重大区别是前者具有动态类型。假设我们也消除了这一点,最终得到了一个没有DOM的静态类型,提前编译的Javascipt。与原生代码相比如何?如果它效率高,为什么不广泛使用?如果没有,现在瓶颈在哪里?在这种状态下,JavaScript几乎与C相同。

*有人可能会说JIT的加载速度更快,但这并不能解释为什么AOT不被用于资源密集型网络应用程序,例如3D视频游戏,其中AOT性能优势非常值得初始AOT编译延迟。 (并且无论如何都存在显着的“游戏加载”延迟)

**无DOM的javascript会使用WebGL / Canvas与用户交互。这目前需要最小的DOM,它定义了最初的HTML5 Canvas,但理论上可以通过修改技术来消除它,如果它值得性能的好处。假设在回答时可以使用无DOM的WebGL / Canvas。

编辑:我说的是客户端编译。

4 个答案:

答案 0 :(得分:2)

实际上,回答你的问题,是的。或者那种。当然,鉴于适当的编译器,您可以提前编译任何内容。

JOT的AOT编译确实是一个奇怪的概念。 AOT编译和“一次编写运行”是一个矛盾,因为通过编译它你说,'我希望它在这个特定的CPU上运行'。

然而,有一些尝试。看看asm.js.你编写你的C程序,然后通过几个箍你将它转换为Javascript模块。然后这个模块由Firefox加载,因为它以某种方式标记(ams =“true”或其他东西),浏览器会尝试提前编译它。结果是ALMOST原生速度。但是,对于代码可以尝试做的事情有很多限制(几乎所有上面提到的那些),除了算法之外我无法看到很多用例。

所有这一切,我觉得其他贡献者的回答过于严厉,因为你正在触及人们实际上想做的事情。

答案 1 :(得分:1)

重要:
你似乎提倡一个剥离的,静态类型的可编译版本的JS。首先要说明的是你不知道JS是什么:一个多范式编程语言,它支持基于Prototype的OO,命令式和函数式编程< / strong> 范例。关键是功能范式。除了Haskell之外,在您定义了自己的中缀运算符之后,它可以是强类型的,函数式语言不能是静态类型的AFAIK。想象一下返回闭包的类C函数定义:

function a = (function (Object g)
{
    char[] closureChar = g.location.href;
    Object foo = {};
    Function foo.bar = char* function()
    {//This is a right mess
        return &closureChar;
    };
}(this));

函数也是第一类对象。使用大量的返回对象的lamda函数,引用可能返回自身的函数,其他函数,对象或原语......你究竟要写所有这些吗? Js函数既是创建范围,构造代码,控制程序流的一种方式,因为它们是您分配给变量的东西。

提前编译JS的问题非常简单:编译代码,必须在如此众多的不同平台上运行:运行Windows,OSX,Linux的台式机/笔记本电脑, UNIX以及具有不同移动浏览器的平板电脑和智能手机...... 即使你确实设法写了&amp;编译JS,在所有平台上运行,JS的速度仍局限于单线程,并在JS引擎上运行(如在VM上运行的Java)。

编译代码客户端已经完成。没错,需要一些时间,但不是很多。它占用大量资源,因此大多数现代浏览器都会以这样的方式缓存代码,以至于已经完成了很多预处理。总是可以编译的东西也将被缓存在它们的编译状态中。 V8是一个开源,快速的JS引擎。如果需要,您可以查看源代码,了解它如何确定JS代码的哪些方面已编译,哪些方面没有。
即便如此,这只是V8的工作原理...... JS引擎更多地与你的代码运行速度有关:有些非常快,有些则不是。有些人在一件事情上更快,其他人在另一个领域的表现优于其他竞争对手。 More details can be read here

剥离DOM部分,不会剥离语言中的任何内容。 DOM API ,不是JS本身的一部分。 JS是一个非常富有表现力的,但在核心,小语言,就像C一样。既没有IO功能留给他们自己的设备,也不能解析DOM。为此,JS的浏览器实现可以访问DOMParser对象 你建议一个最小的DOM ...嘿,任何有意义的人都是改进的DOM API。它远不是关于网络的最好的事情。但你必须意识到DOM和JS是独立的实体。 DOM(和DOM API)由W3管理,而ECMA负责JS。彼此之间没有任何关系。这就是为什么DOM无法从JS中删除&#34; 的原因:从一开始就不是它的一部分。

由于您将JS与C ++进行比较:您可以编写可以在Windows和Linux机器上编译的C ++代码,但这并不像听起来那么容易。但既然你自己提到C ++,我想你也可能知道这一点 说到这一点,如果你在C ++和JS之间看到的唯一真正的区别是静态与动态类型,你真的应该花更多的时间来学习JS。

虽然它的语法类似于C语言,但语言本身与Lisp(即函数式编程)有更多的相似之处。它本身并不知道类,但是使用原型......说实话,动态类型实际上并不是那么重要。

所以,底线:
编译JS以在每台机器上运行将导致类似MS的.NET框架。这背后的哲学是:&#34;写一次,到处运行&#34; ......根本没有结果是真的。
Java X平台,但这只是因为它没有编译为本机代码,而是在虚拟机上运行。 最后,ECMAScript标准(JS是其最常见的实现)并不是那么好,而且是该领域所有大型竞争对手共同努力的结果:Mozilla,谷歌,微软和一些不相关的瑞士公司。这是一个巨大的妥协。想象一下,这三位大牌同意为JS编写一个编译器。微软只会提出JScript compiler为最佳,谷歌将有自己的想法,Mozilla可能会有3个不同的编译器,具体取决于社区的需求。

修改
你做了一个编辑,澄清你在谈论客户端JS。因为您觉得有必要指定它,我觉得您似乎并不完全确定JS结束的位置以及浏览器接管的位置。
JS被设计为一种非常便携的语言:它没有IO功能,支持多种开发范例,并且(最初)是一种完全解释的语言。确实,它是在考虑到Web的情况下开发的,但你可以,有些人可以使用这种语言来查询数据库(MongoDB),作为替代批处理脚本语言(JScript)或服务器端脚本语言(骨干, Node.js的,...)。有些人使用ECMAScript(JS的基本标准)来制作自己的编程语言(是的,我正在谈论Flash ActionScript)。

根据用例,JS将获得对该语言不是原生的对象/ API的访问权限document[Object http].createServer,{{1}分别用于DOM访问,Web服务器功能和IO)。那些往往形成瓶颈,而不是语言本身。

正如我所暗示的那样,JS 最初是一种解释性语言。就像现在这样,在过去十年中,编译语言和解释语言之间的分歧已经逐渐消失,说实话。
C / C ++曾经是严格编译的语言,但在某些情况下(.NET)C ++代码不再需要编译成机器代码了......
同时,像Python这样的脚本语言被用于许多目的,它们通常被认为是一种编程语言,因为术语脚本语言以某种方式暗示着&#34;较小的语言&#34;
几年前,随着PHP5的发布,ZendEngine2也被发布了。从那时起,PHP被编译为字节码并在虚拟机上运行。您可以使用APC缓存字节码。 bcompiler允许您从PHP代码生成独立的可执行文件,Facebook的HPHPc(已弃用)用于将PHP编译为C ++,然后生成本机代码。现在,facebook使用HHVM,这是一个自定义虚拟机。 Find out more here

在JavaScript解释器(现在称为引擎)中可以看到相同的演变。它们并不是你日常的解析和执行线程,因为你似乎仍然认为它们是。在内存管理,JITCompilation(tail stack optimizing even),优化和你有什么方面,还有很多巫术正在进行...... 所有伟大的事情,但这些使得确定实际瓶颈的位置变得相当困难。每个引擎优化的方式与IE6的差异甚至不同于IE10,因此几乎无法确定瓶颈。如果一个浏览器需要10秒钟来完成DOM密集型任务,另一个浏览器可能只需要1~2秒。但是,如果相同的浏览器互相攻击以检查RegExp对象的性能,则引导可能在另一只脚上。
我们不要忘记,在您撰写关于您的调查结果的博客文章之后,您必须检查这两个浏览器是否都发布了一个声称可以加速确定的新版本/更新任务。

答案 2 :(得分:0)

我倾向于认为它会以相当大的速度更快,但是它也限制了您可以轻松完成的工作,因为DOM在某些方面确实非常有效。

DOM是为文档设计的;它并不是在设计时就考虑到UI的。就是说,由于DOM本质上是静态的,所以DOM最困难的问题之一就是使其与模型保持同步,即使最小的更改也可能导致重排(这可能很慢)。 React和其他虚拟DOM框架试图通过一次替换整个DOM并使用VDOM diff来最大程度地减少更改来避开这种情况。另一方面,使用画布可以使屏幕与模型保持同步非常简单,因为您只需使用新数据重新绘制画布并继续操作即可。

将渲染图移到画布上会切掉中间人,使您可以自己进行渲染,布局和样式设置。权衡是显而易见的。现在,您必须手动管理所有事件处理和滚动,此外,嵌入实际文档将是一场噩梦。如果有某种框架设计解决方案,那么它可能是可行的,高性能的替代方案,而不会造成DOM崩溃,但是对于新闻网站,博客,社交媒体或大多数文本繁重的网站来说,这可能毫无意义。这种事情可能会给绘图应用程序,游戏甚至聊天应用程序带来巨大的性能提升,但是没有其他领域会受益。还是他们?我很高兴被证明是错误的。

DOM非常像一个方钉,我们已经设法将其塞入各种怪异形状的孔中。它并不是所有工具的最佳工具,但是当您只有一把锤子时,一切看起来就像钉子。

答案 3 :(得分:-1)

一切都不是关于性能,性能仍然是能力的次要。您首先获得一些语言(re:javascript)以使网站成为可能,然后改进语言。如果从JS中删除DOM操作,使其编译为本机代码,那么我们将使用什么用于Web? javascript存在的原因之一,我们不在Web中使用C / C ++,因为它具有进行DOM操作的能力,并且不需要编译成特定于机器的格式,因此可以普遍执行。 / p>

除了我有一个javascript的名字,它被剥夺了DOM操作,静态类型,提前编译:它是Java:)

您的问题确实是为什么我们不将Java用于网站,因为它的表现要好得多 - 想一想。有一天我们会在那里,但还没有。