4

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

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

如果新的瓶颈是 DOM,如果我们也消除它呢?一个无 DOM 的编译 Javascript 会和原生代码一样高效吗?如果是,为什么不在网络上广泛完成**?如果不是,那么现在的性能瓶颈在哪里?

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

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

**无 DOM 的 javascript 将使用 WebGL/Canvas 与用户交互。目前这需要最少的 DOM,它定义了最初的 HTML5 Canvas,但如果值得提高性能,理论上可以通过修改技术来消除这种情况。假设回答时可以使用 DOM-less WebGL/Canvas。

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

4

4 回答 4

4

其实,回答你的问题,是的。或之类的。因为当然你可以在给定适当的编译器的情况下提前编译任何东西。

确实,Javascript 的 AOT 编译是一个有点奇怪的概念。AOT 编译和“编写一次在任何地方运行”是矛盾的,因为编译它是在说“我希望它在这个特定的 CPU 上运行”。

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

尽管如此,我觉得其他贡献者的回答过于苛刻,因为你正在触及人们实际上正在尝试做的事情。

于 2013-11-13T21:28:48.120 回答
0

重要提示:
您似乎提倡剥离的、静态类型的可编译 JS 版本。首先表明您对 JS 是什么一无所知:一种多范式编程语言,支持基于原型的 OO、命令式和函数式编程范式。关键是功能范式。除了在定义自己的中缀运算符后可以进行强类型化的 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 的台式机/笔记本电脑以及平板电脑和智能手机移动浏览器...
即使您确实设法编写和编译运行在所有平台上的 JS,JS 的速度仍然受限于它是单线程的,并且运行在 JS 引擎上(就像 Java 在 VM 上运行)。

编译代码客户端已经完成。诚然,这需要一些时间,但不是很多。这是相当资源密集型的,因此大多数现代浏览器都会以已经完成大量预处理的方式缓存代码。总是可以编译的东西,也将被缓存在它们的编译状态中。V8 是一个开源的、快速的 JS 引擎。如果需要,您可以查看源代码,了解如何确定 JS 代码的哪些方面已编译,哪些未编译。
即便如此,这只是 V8 的工作方式...... JS 引擎与代码运行的速度有更多关系:有些非常快,有些则不然。有些人在一件事上速度更快,而另一些人在另一个领域的表现优于所有竞争对手。更多细节可以在这里阅读

剥离 DOM 部分并没有从语言中剥离任何东西。DOM API不是 JS 本身的一部分。JS 是一种表达能力很强,但在核心,小型语言,就像 C 一样。两者都没有留给自己的设备的 IO 能力,也无法解析 DOM。为此,JS 的浏览器实现可以访问 DOMParser 对象。
您建议使用最小的 DOM ......嘿,任何人都支持改进的 DOM API。这远非网络上最好的东西。但是你必须意识到 DOM 和 JS 是独立的实体。DOM(和 DOM API)由 W3 管理,而 ECMA 负责 JS。彼此都没有任何关系。这就是为什么 DOM 不能从 JS 中“剥离”出来的原因:它从一开始就不是它的一部分。

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

虽然它的语法类似于 C,但语言本身与 Lisp 有更多的相似之处(即函数式编程)。它不知道类本身,但使用原型……说实话,动态类型真的没什么大不了的。

所以,底线:
编译 JS 以在每台机器上运行将导致类似于 MS 的 .NET 框架的东西。其背后的理念是:“一次编写,到处运行” ……事实证明这根本不是真的。
JavaX 平台的,但这仅仅是因为它没有编译为本机代码,而是在虚拟机上运行。
最后,ECMAScript 标准(JS 是其最常见的实现)并不是那么好,它是该领域所有大型竞争对手共同努力的结果:Mozilla、谷歌、微软和一些无关紧要的瑞士公司。这是一个巨大的妥协。想象一下这三个大牌同意一起为 JS 做一个编译器。微软将推出其JScript 编译器作为最好的,Google 将有自己的想法,而 Mozilla 可能会准备好 3 种不同的编译器,具体取决于社区的需求。

编辑:
您进行了编辑,澄清您在谈论客户端 JS。因为您觉得有必要指定这一点,所以我觉得您似乎并不完全确定 JS 在哪里结束,以及浏览器在哪里接管。
JS 被设计成一种非常可移植的语言:它没有 IO 功能,支持多种开发范式,并且(最初)是一种完全解释性的语言。诚然,它是在考虑 Web 的情况下开发的,但是您可以并且有些人确实可以使用这种语言来查询数据库 (MongoDB),作为替代的批处理脚本语言 (JScript) 或服务器端脚本语言 (backbone, node.js,...)。有些人使用 ECMAScript(JS 的基本标准)来制作自己的编程语言(是的,我说的是 Flash ActionScript)。

根据用例,JS 将被授予访问非语言原生对象/API 的权限(document, [Object http].createServer[Object file].readFileSync分别用于 DOM 访问、Web 服务器功能和 IO)。这些往往构成瓶颈,而不是语言本身。

正如我所暗示的,JS最初是一种解释性语言。就像现在一样,编译语言和解释语言之间的分界线在过去十年中一直在消退,老实说。
C/C++ 曾经是严格编译的语言,但在某些情况下(.NET)C++ 代码不再需要编译为机器代码......
同时,像 Python 这样的脚本语言被用于很多目的,它们'通常被视为一种编程语言,因为脚本语言一词在某种程度上暗示了一种“次要语言”
几年前,随着 PHP5 的发布,ZendEngine2 也发布了。从那时起,PHP 被编译为字节码并在虚拟机上运行。您可以使用 APC 缓存字节码。bcompiler 允许您从 PHP 代码生成独立的可执行文件,就像 Facebook 的 HPHPc(已弃用)用于将 PHP 编译为 C++,然后编译为本机代码一样。现在,facebook 使用 HHVM,这是一个自定义虚拟机。在这里了解更多信息

在 JavaScript 解释器(现在称为引擎)中可以看到同样的演变。它们不是你每天解析和执行的旧线程,你似乎仍然认为它们是。在内存管理、JITCompilation(甚至尾栈优化)、优化以及你有什么方面,有很多魔法正在发生……
所有伟大的事情,但这些使得很难确定实际的瓶颈在哪里。每个引擎优化的方式比IE6与IE10的差异还要大,因此几乎不可能确定瓶颈。如果一个浏览器需要 10 秒来完成一项 DOM 密集型任务,那么另一个浏览器可能只需要 1~2 秒。但是,如果相同的浏览器相互竞争以检查 RegExp 对象的性能,则启动可能会在另一只脚上。
我们不要忘记,在您撰写有关您的发现的博客文章之后,您必须检查是否没有任何浏览器发布了声称可以加快某些任务的新版本/更新。

于 2013-05-04T17:27:56.777 回答
0

我倾向于认为它会快很多,但它也限制了你可以轻松完成的事情,因为 DOM 实际上对于某些事情非常有效。

DOM 是为文档设计的;它的设计并没有真正考虑到 UI。也就是说,DOM 最困难的问题之一是使其与模型保持同步,因为 DOM 本质上是静态的,即使是最小的更改也会导致回流(这可能很慢)。React 和其他虚拟 DOM 框架试图通过一次替换整个 DOM 并使用 VDOM 差异来最小化更改量来回避这一点。另一方面,使用画布使屏幕与模型保持同步变得非常简单,因为您可以使用新数据重新绘制画布并继续前进。

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

DOM 在很大程度上是一个方形钉子,我们已经设法将其装入各种形状怪异的孔中。它不是最好的工具,但是当你只有一把锤子时,一切看起来都像钉子。

于 2019-02-06T20:16:13.493 回答
-1

一切都不是关于性能的,性能仍然是仅次于能力的。您首先获得一些语言(re:javascript)以使网站成为可能,然后改进语言。如果你从 JS 中剥离出 DOM 操作,让它编译为原生代码,那么我们将在 web 中使用什么?javascript 存在的原因之一,我们不在网络中使用 C/C++ 是因为它具有执行 DOM 操作的能力,它不需要编译成机器特定的格式,因此是通用的可执行文件。

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

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

于 2013-05-04T16:45:32.503 回答