5

通过 Tracemonkey、Squirrelfish 和 V8 项目,有很多大写 C、大写 S 的计算机科学进入 Javascript。这些项目(或其他项目)中的任何一个都解决了 DOM 操作的性能问题,还是纯粹与 Javascript 计算相关?

4

2 回答 2

13

纯 DOM 操作(getElementById/Tagname/Selector、nextChild 等)的性能不受影响,因为它们已经在纯 C++ 中。

JS 引擎的改进将如何影响性能确实在一定程度上取决于用于性能改进的特定技术,以及 DOM->JS 桥的性能。

前者的一个例子是 TraceMonkey 对所有对 JS 函数的调用的依赖。因为在 JS 遇到无法内联的代码(本机代码、真正的多态递归、异常处理程序)的任何点,跟踪都有效地内联了执行路径,所以跟踪被中止,执行回退到解释器。TM 开发人员正在做大量工作来改进可跟踪的代码量(包括处理多态递归),但实际跟踪对任意本机函数(例如 DOM)的调用是不可行的。出于这个原因,我相信他们正在考虑在 JS 中实现更多的 DOM(或者至少以 JS 友好的方式)。也就是说,当代码可追溯时,TM 可以做得非常好,因为它可以降低大多数“对象”

JavaScriptCore(这是 SquirrelFish Extreme 所在的地方)和 V8 有一个更相似的方法,因为它们都立即 JIT 所有 JS 代码并生成更具推测性的代码(例如,如果您正在这样做a*b,它们生成的代码假定a并且b是数字并回退如果不是,则代码异常缓慢)。与跟踪相比,这有很多好处,即您可以 jit 所有代码,无论它是否调用本机代码/抛出异常等,这意味着单个 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.xa.y都是数字,而 TM 将生成a只检查一次类型的代码,并且可以(所有事情都是相等)只是相乘a.x而不a.y检查它们是否是数字。

如果您目前正在查看纯粹的执行速度,那么就会出现好坏参半的情况,因为每个引擎在某些任务上确实比其他引擎做得更好——TraceMonkey 在许多纯数学测试中获胜,V8 在高度动态的情况下获胜,JSC 获胜,如果有的话混合物。当然,虽然今天确实如此,但明天可能不会,因为我们都在努力提高性能。

我提到的另一个问题是 DOM<->JS 绑定成本——这实际上可以在 Web 性能中发挥非常重要的作用,最好的例子是 Dromaeo 基准测试中的 Safari 3.1/2 与 Chrome。Chrome 基于 WebKit 的 Safari 3.1/2 分支,因此假设类似的 DOM 性能是相当安全的(编译器差异可能会导致某种程度的差异)。在这个基准测试中,Safari 3.1/2 实际上击败了 Chrome,尽管 JS 引擎显然要慢得多,这基本上是由于 JSC/WebCore(WebKit 的 dom/rendering/etc)和 V8/WebCore 之间更有效的绑定

目前查看 TM 的 DOM 绑定似乎是不公平的,因为他们还没有完成他们想做的所有工作(唉)所以他们只是依靠解释器:-(

..

Errmmm,这比预期的要长一些,所以对原始问题的简短回答是“这取决于”:D

于 2009-01-02T08:42:34.547 回答
4

它们是纯 JavaScript。除非在JS中实现了特定的 DOM 方法调用,否则它们几乎没有效果(但并不是说还没有减少此类调用的开销)。

DOM 优化是一个完整的“松鼠 蜘蛛鱼”的另一锅......布局甚至渲染引擎都在发挥作用,每个浏览器都有自己的实现和优化策略。

于 2009-01-02T06:22:56.233 回答