是什么阻碍了Ruby和Python获得V8的Javascript速度?

是否有任何Ruby / Python特性阻碍了V8引擎的优化实现(例如内联缓存) ?

Python是由谷歌的人共同开发的,所以它不应该被软件专利所阻止。

或者这是谷歌在V8项目中投入的资源问题。

80252 次浏览

性能似乎并不是核心Python开发人员的主要关注点,他们似乎觉得“足够快”就足够好了,而且帮助程序员提高工作效率的功能比帮助计算机更快地运行代码的功能更重要。

然而,确实有一个谷歌项目unladen swallow,用于生成一个与标准解释器兼容的更快的Python解释器。PyPy是另一个旨在生成更快Python的项目。还有Psyco, PyPy的前身,它可以在不更改整个解释器的情况下为许多Python脚本提供性能提升,还有Cython,它允许您使用非常类似于Python语法的东西为Python编写高性能的C库。

这很大程度上与社区有关。Python和Ruby在很大程度上没有企业支持。没有人会因为全职从事Python和Ruby而获得报酬(特别是他们不会因为一直从事CPython或MRI而获得报酬)。另一方面,V8得到了世界上最强大的IT公司的支持。

此外,V8可以更快,因为对V8的人来说唯一重要的事情是解释器——他们没有标准库可以工作,不需要考虑语言设计。他们只编写解释器。就是这样。

这与知识产权法无关。Python也不是由谷歌的人共同开发的(它的创建者和其他一些提交者一起在那里工作,但他们没有为Python工作而获得报酬)。

Python速度的另一个障碍是Python 3。它的采用似乎是语言开发人员最关心的问题——以至于他们冻结了新语言特性的开发,直到其他实现赶上来。

关于技术细节,我不太了解Ruby,但是Python有很多地方可以使用优化(Unladen Swallow,一个谷歌项目,在失败之前就开始实现这些)。这是他们计划的一些优化。如果CPython实现了像PyPy一样的JIT,我可以看到Python在未来达到V8的速度,但这在未来几年似乎不太可能(现在的重点是采用Python 3,而不是JIT)。

许多人还认为Ruby和Python可以从删除它们各自的全局解释器锁中获益良多。

你还必须明白,Python和Ruby都是比JS重得多的语言——它们在标准库、语言特性和结构方面提供了更多。仅面向对象的类系统就增加了大量的权重(我认为是一种很好的方式)。我几乎认为Javascript是一种被设计为嵌入式的语言,就像Lua(在许多方面,它们是相似的)。Ruby和Python有更丰富的特性集,这种表现力通常是以速度为代价的。

是什么阻碍了Ruby和Python获得V8的Javascript速度?

什么都没有。

好吧,钱。(还有时间、人力和资源,但如果你有钱,这些都是可以买到的。)

V8有一个优秀的、高度专业化的、经验丰富(因此高薪)的工程师团队,他们有几十年的经验(我是单独说的)。总的来说,它更像是几个世纪)为动态OO语言创建高性能执行引擎。他们基本上是创建Sun HotSpot JVM(以及其他许多JVM)的同一群人。

首席开发人员Lars Bak已经在vm上工作了25年(所有这些vm都已经发展到V8),这基本上是他的整个(职业)生涯。一些编写Ruby vm的人甚至不到25岁。

是否有Ruby / Python特性阻碍了V8引擎的优化实现(例如内联缓存)?

考虑到至少IronRuby、JRuby、MagLev、MacRuby和Rubinius都有单态(IronRuby)或多态内联缓存,答案显然是否定的。

现代Ruby实现已经做了大量的优化。例如,对于某些操作,Rubinius的Hash类比YARV的更快。现在,这听起来并不令人兴奋,直到你意识到Rubinius的Hash类是用100%纯Ruby实现的,而YARV的类是用100%手工优化的C实现的。

所以,至少在某些情况下,Rubinius可以生成比GCC更好的代码!

或者这是谷歌在V8项目中投入的资源问题。

是的。不只是谷歌。V8的源代码已经有25年的历史了。在V8上工作的人还创建了Self VM(迄今为止创建的最快的动态OO语言执行引擎之一),Animorphic Smalltalk VM(迄今为止创建的最快的Smalltalk执行引擎之一),HotSpot JVM(有史以来创建的最快的JVM,可能是最快的VM时期)和OOVM(有史以来创建的最高效的Smalltalk VM之一)。

事实上,V8的首席开发人员Lars Bak曾致力于其中的每一个,还有其他一些。

我刚刚遇到了这个问题,还有一个很大的技术原因导致了性能差异,但没有提到。Python有一个非常强大的软件扩展生态系统,但这些扩展大多数是用C或其他低级语言编写的,以提高性能,并与CPython API紧密相关。

有很多众所周知的技术(JIT、现代垃圾收集器等)可以用来加速CPython的实现,但所有这些技术都需要对API进行重大更改,破坏了过程中的大多数扩展。CPython会更快,但是Python吸引人的很多东西(广泛的软件堆栈)将会丢失。举个例子,有一些更快的Python实现,但与CPython相比,它们几乎没有吸引力。

高度优化JavaScript解释器的动力很大,这就是为什么我们看到Mozilla、谷歌和微软之间投入了如此多的资源。JavaScript必须在一个人(通常没有耐心)等待它的时候实时下载、解析、编译和运行,它必须在一个人与它交互的时候运行,而且它是在一个不受控制的客户端环境中完成这些工作,可能是一台计算机、一部电话或一台烤面包机。为了在这些条件下有效地运行,它必须是高效的。

Python和Ruby运行在一个由开发人员/部署人员控制的环境中。一个健壮的服务器或桌面系统,限制因素通常是内存或磁盘I/O,而不是执行时间。或者可以利用缓存等非引擎优化。对于这些语言,关注语言和库特性集而不是速度优化可能更有意义。

这样做的附带好处是,我们拥有两个出色的高性能开源JavaScript引擎,它们可以并且正在被重新用于各种应用程序,例如Node.js。

我相信这是因为不同的设计优先级和用例目标。

一般来说,脚本语言(又称动态语言)的主要目的是在本地函数调用之间充当“粘合剂”。这些原生功能应a)覆盖最关键/最常用的领域b)尽可能有效。

下面是一个例子: jQuery排序导致iOS Safari冻结 那里的冻结是由于过度使用get-by-selector调用造成的。如果get-by-selector可以在本地代码中实现,那么就不会有这样的问题了

考虑一下V8演示中经常使用的光线跟踪演示。在Python世界中,它可以在本机代码中实现,因为Python为本机扩展提供了所有工具。但在V8领域(客户端沙盒),除了让VM尽可能高效之外,你没有其他选择。所以唯一的选择是使用脚本代码来实现光线跟踪器。

不同的优先级和动机。

Sciter中,我通过在本地实现几乎完整的jquery核心来进行测试。在实际任务中,如ScIDE(由HTML/CSS/Script制成的IDE),我相信这样的解决方案比任何VM优化都要好得多。

误导问题。V8是JavaScript的JIT(即时编译器)实现,在它最流行的非浏览器实现Node.js中,它是围绕一个事件循环构建的。CPython不是JIT &没有事件。但是这些在Python中最常见的存在于PyPy项目中——一个CPython 2.7(很快就会是3.0+)兼容的JIT。还有很多事件服务器库,比如Tornado。PyPy运行Tornado和Node.js之间存在真实世界的测试,性能差异很小。

正如其他人所提到的,Python有一个PyPy形式的高性能JIT编译器。

制定有意义的基准测试总是很微妙的,但我碰巧有一个用不同语言编写的简单的k - means基准测试——你可以找到它在这里。其中一个限制是各种语言都应该实现相同的算法,并且应该力求简单和惯用(而不是为了速度而优化)。我已经编写了所有的实现,所以我知道我没有作弊,尽管我不能声称我所编写的所有语言都是惯用的(我对其中一些语言只有粗略的了解)。

我没有任何明确的结论,但PyPy是我得到的最快的实现之一,比Node好得多。相反,CPython位于排名最慢的一端。

这种说法并不完全正确

就像V8只是JS的一个实现一样,CPython只是Python的一个实现。Pypy的性能与V8相当

此外,还有感知性能的问题:由于V8本身是非阻塞的,Web开发会导致更高性能的项目,因为您节省了IO等待时间。V8主要用于开发Web,其中IO是关键,所以他们将它与类似的项目进行比较。但是,除了web开发,你还可以在许多其他领域使用Python。你甚至可以在许多任务中使用C扩展,比如科学计算或加密,并以出色的性能处理数据。

但是在网络上,大多数流行的Python和Ruby项目都是阻塞的。尤其是Python,它继承了同步WSGI标准,像著名的Django这样的框架就是基于它的。

你可以编写异步Python(比如Twisted、Tornado、gevent或asyncio)或Ruby。但这种做法并不常见。最好的工具仍然是阻塞的。

然而,这也是Ruby和Python的默认实现速度不如V8的原因之一。

经验

就像Jörg W Mittag指出的那样,V8的开发者都是VM天才。Python是由一群充满激情的人开发的,在很多领域都很出色,但在VM调优方面并不专业。

资源

Python软件基金会只有很少的钱:小于40k在一年内投资于Python。当你认为像谷歌、Facebook或苹果这样的大公司都在使用Python时,这有点疯狂,但这是丑陋的事实:大多数工作都是免费完成的。在Java之前就存在的支持Youtube的语言是由志愿者手工制作的。

他们是聪明和敬业的志愿者,但当他们发现自己在某个领域需要更多的能量时,他们不能要求30万美元来雇佣一个该领域的顶级专家。他们必须四处寻找愿意免费做这件事的人。

虽然这是有效的,但这意味着你必须非常小心你的优先级。因此,现在我们需要看看:

目标

即使拥有最新的现代特性,编写Javascript也很糟糕。你有范围问题,很少的集合,糟糕的字符串和数组操作,除了日期,数学和正则表达式之外几乎没有标准列表,甚至对于非常常见的操作也没有语法糖。

但在V8引擎中,你有速度。

这是因为,速度是谷歌的主要目标,因为它是Chrome页面渲染的瓶颈。

在Python中,可用性是主要目标。因为这几乎从来都不是项目的瓶颈。这里的稀缺资源是开发人员的时间。它是为开发人员优化的。

因为JavaScript实现不需要关心其绑定的向后兼容性。

直到最近,JavaScript实现的唯一用户还是web浏览器。由于安全需求,只有web浏览器供应商有权通过编写到运行时的绑定来扩展功能。因此,没有必要保持绑定的C API向后兼容,可以要求web浏览器开发人员随着JavaScript运行时的发展更新源代码;反正他们在一起工作。即使是V8,作为游戏的后来者,也是由一个非常有经验的开发者领导的,也已经改变了API,因为它变得更好了。

OTOH Ruby(主要)用于服务器端。许多流行的ruby扩展被编写为C绑定(考虑RDBMS驱动程序)。换句话说,如果不保持兼容性,Ruby就永远不会成功。

今天,这种差异在某种程度上仍然存在。使用node.js的开发人员抱怨很难保持他们的本机扩展向后兼容,因为V8会随着时间改变API(这也是node.js被分叉的原因之一)。IIRC ruby在这方面仍然采取更为保守的方法。

V8由于JIT、曲轴、类型推断器和数据优化代码而快速。标记指针,双精度对象的nan标记。 当然,它会在中间进行正常的编译器优化。< / p >

普通的ruby, python和perl引擎都不做这些,只是做了一些基本的优化。

唯一接近的主要虚拟机是luajit,它甚至不做类型推断、常量折叠、nan标记和整数,但使用类似的小代码和数据结构,不像坏语言那么胖。 我的原型动态语言,potion和p2有和luajit相似的特性,并且性能优于v8。有了可选的类型系统,“渐变类型”,你可以很容易地超越v8,因为你可以绕过曲轴。看到飞镖。< / p >

已知的优化后端,如pypy或jruby仍然受到各种过度工程技术的影响。