通过Tracemonkey,Squirrelfish和V8项目,有很多大写C,大写S计算机科学都在Javascript中使用。这些项目(或其他项目)中的任何一个是否解决了DOM操作的性能,还是它们纯粹与Javascript计算有关?
最佳答案
纯DOM操作(getElementById/Tagname/Selector,nextChild等)的性能不受影响,因为它们已经在纯C++中。
JS引擎改进如何影响性能确实在一定程度上取决于用于性能改进的特定技术以及DOM-> JS桥的性能。
前者的一个示例是TraceMonkey依赖于对JS函数的所有调用。因为跟踪有效地内联了JS击中无法内联的代码( native 代码,真正的多态递归,异常处理程序)的任何点的执行路径,所以中止了跟踪,执行回落到解释器。 TM开发人员正在做大量工作来改善可跟踪的代码量(包括处理多态递归),但是在现实中对任意本地函数(例如DOM)的调用进行跟踪是不可行的。因此,我相信他们正在考虑在JS中(或至少以JS友好的方式)实现更多的DOM。就是说,当代码是可跟踪的时,TM可以做得非常出色,因为它可以将大多数“对象”降低为更有效和/或 native 的等效对象(例如,使用计算机整数而不是JS Number实现)。
JavaScriptCore(SquirrelFish Extreme所在的地方)和V8具有更相似的方法,因为它们都立即将所有JS代码JIT并生成更具推测性的代码(例如,如果您正在执行a*b
,则它们会生成假定a
和b
为数字的代码并返回到异常慢的代码(如果不是)。与跟踪相比,这有很多好处,即,您可以将所有代码都绑定(bind)在一起,无论它是否调用 native 代码/抛出异常等,这意味着单个DOM调用不会破坏性能。缺点是所有代码都是推测性的-TM会内联调用Math.floor等,但是最好的JSC/V8可以做到的等效于a=Math.floor(0.5)
-> a=(Math.floor == realFloor) ? inline : Math.floor(0.5)
,这在性能和内存使用上都付出了代价,但事实并非如此。并不是特别可行。这样做的原因是前期编译,而TM仅在运行JIT之后才进行编码(因此确切知道调用了什么函数),JSC和V8没有真正的依据可以做出这样的假设,并且基本上可以猜测(并且目前还没有尝试过)这)。 V8和JSC试图解决此问题的一件事是跟踪他们过去所看到的内容,并将其整合到执行路径中,两者都使用多种技术组合来进行此缓存,特别是在特殊情况下它们重写指令流的一小部分,而在其他情况下,它们会保留带外缓存。概括地说,如果您有需要的代码
a.x * a.y
V8和JSC将检查“隐式类型”/“结构”两次-每次访问一次,然后检查
a.x
和a.y
都是数字,而TM将生成仅检查a
类型的代码,并且可以(在所有条件都相同的情况下),只需将a.x
和a.y
相乘即可,而无需检查它们是否为数字。如果您正在查看纯粹的执行速度,则目前情况有些复杂,因为每个引擎在某些任务上的表现似乎都比其他引擎好-TraceMonkey在许多纯粹的数学测试中胜出,V8在高度动态的情况下胜出,JSC在有条件的情况下胜出混合物。当然,尽管今天是对的,但也许不是明天,因为我们都在努力提高性能。
我提到的另一个问题是DOM <-> JS绑定(bind)成本-这实际上可以在Web性能中发挥非常重要的作用,最好的例子是Safari 3.1/2 vs Dromaeo基准测试中的Chrome。 Chrome浏览器基于WebKit的Safari 3.1/2分支,因此假设类似的DOM性能是相当安全的(编译器差异可能会导致一定程度的差异)。在此基准测试中,尽管Safari 3.1/2具有一个明显慢得多的JS引擎,但它实际上击败了Chrome,这主要是由于JSC/WebCore(WebKit的dom/rendering/etc)与V8/WebCore之间的绑定(bind)效率更高
当前查看TM的DOM绑定(bind)似乎是不公平的,因为他们还没有完成他们想要做的所有工作(alas),所以他们只是依靠解释器:-(
..
Errmmm,持续时间比预期的要长,所以对原始问题的简短回答是“取决于”:D
关于javascript - 各种Javascript优化项目如何影响DOM性能?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/406097/