新时代新潮流 WebOS【17】需要不需要 JavaScript

2009-05-04 20:37

Netscape 于 1994 年成立,并迅速走红,1996 年占据了浏览器 市场接近 90% 的市场份额。然而从 1997 年开始,在微软 IE 浏览器的强大攻势下,Netscape 败走麦城,转眼到了 2006 年,Netscape 的市 场份额只剩下 1% 不到。虽然 Netscape 昙花一现,但是短暂的辉煌,却留下了很多技术遗产,影响至今。

Brendan Eich 1986 年毕业于 UIUC,1995 年入职 Netscape,当时正值 Netscape 如日中天。入职后不久,Brendan Eich 成功说服他的领导,开始了 JavaScript 的研究和开发,成为 JavaScript 之父。Brendan 现在供职于 Mozilla.com。

Brendan 在 2008 年 8 月 23 日的博客中写到,“我极其高兴地宣布,TraceMonkey 正式投入使用。这是 Firefox 所使用的 SpiderMonkey JavaScript engine 的一次更新换代,TraceMonkey 将植入在 Firefox3.1 版本,其亮点在于使用了一种新型的 Just-In-Time(JIT)编译器,使 JavaScript 的运行效率提高一个数量级以上。”

Benchmark comparison for JIT Figure 1. Benchmark comparison for JIT

图一显示了没有配备 JIT 的 Firefox 3.0 的 SpiderMonkey JavaScript engine,与配备了 JIT 的 TraceMonkey JavaScript engine 的运行速度的比较。JavaScript 包含的功能很多,处理各个功能的速度快慢不一。譬如,JavaScript engine 处理 Image object 的速度非常快,但是处理数学运算例如 matrix,通常会慢很多。Brendan 团队用四种不同的测试用例集(benchmarks),多方 面测试和比较,配备了 JIT 与没有配备 JIT 的两种 JavaScript engines 的运行效率。结论是配备了 JIT,能使 JavaScript engine 的速度提高一倍甚至更多。

Brendan 的博客隐含三个问题,1. 为什么 JavaScript engine 的运行速度很重要?2. 为什么 JIT 能够使 JavaScript engine 运行速度大大加快?3. 为什么选择 JIT 技术,而不是预先编译的办法?

第一个问题很好回答,因为 JavaScript 的应用领域日益广泛,譬如 Google Docs,试图用 Ajax 技术实现基于浏览器的在线的 Office 软件,与离线的 Microsoft 的 Word,PPT,Excel 甚至 Visio 等等产 品竞争。但是 Microsoft Office 软件包含的运算逻辑非常复杂,譬如绘图软件 Visio 包含了大量的计算几何运算。虽然 JavaScript 应付简单的动态网页游刃有余,但是 面对这些大计算量的应用,JavaScript engine 的运行速度就至关重要。

第二个问题,相对于逐句解析,JIT 的优势在于可以 整段地编译源代码,而且缓存编译的结果,这样就避免了重复解析那些先前已经解析过了的源代码。另外整段编译并缓存编译结果,有利于优化代码,通常包括 inline expansion, dead code elimination, constant propagation, loop transformation, register allocation 以及 automatic parallelization 等等。当然,优化代码是需要时间的,优化程度越高,运行时效率越高,但是启动时间越长。

第三个问题,为什么不用预先编译的办法。所谓预先编译,指的是开发者预先编译,在网站上发布编译好的二进制代码,而不是源代码。当浏览器访问到相关网页时,随即下载这些编 译好的二进制代码,然后直接运行之,省略掉了 JIT 编译的过程,也回避了逐句解析运行效率低下的弊端。为什么不预先编译 JavaScript 源代码?这个 问题表面上看起来也很容易回答,因为 Java Applet 曾经尝试过预先编译的办法,但是 Java Applet 以失败告终。这段历史教训似乎说明了,网页不应该绑定编译过的二进制代码,而最好只绑定文本形式的源代码。

但是如果深究一下 Java Applet 失败的原因,会发现不应该把 Java Applet 失败的罪责推卸给预先编译。

关于 Java Applet 失败的原因,Wikipedia 谈到了兼容性的历史纠葛。Java 的卖点是 write once, run anywhere,所以 Sun 公司非常重视 Java 的兼容性。可是微软推出 IE 浏览器早期版本的时候,使用的 Java 虚拟机是微软自己的产品,其中包含一 些非标准的 Java 功能。这样,在 IE 浏览器中能够运行的 Java Applet,不一定能够在其它浏览器中顺利运行。Sun 找微软谈判,让微软去掉这些不合标准的 Java 功能,未果,于是对簿法庭。官司一打就是几年,控 辩双方精疲力竭。最后,微软宣布不再开发微软自己的 Java 虚拟机,同时 IE 浏览器也不预装 Sun 版的 Java 虚拟机。很多普通用户不知道如何自行安装 Java,当他们用浏览器访问网站时,如果遇到包含 Java Applet 的网页,就必须当场下载并安装 JRE,这是一个非常耗时的过程,网页迟迟不能显示出来,导致用户体验很差。

假设历史上没有发生微软和 Sun 关于 Java 版本之争,Java Applet 会不会大行其道呢?未必。

Wikipedia 还提到另一个 Java Applet 失败的原因,初看起来感觉有点吹毛求疵,但是反复想想,觉得其中大有深意。Wikipedia 说,以 Netscape 为代表的一些浏览器,在 处理占满整个浏览器页面的 Java Applets 的时候,效果不佳,但是 JavaScript 勉强还行。让 Java Applet 脱离原先的浏览器页面,弹出一个新的窗口,也不是一个好办法。因为这样做,原先的浏览器页面就无所事事,用户会不自觉地关闭它,但是不曾想, 母体关闭了,Java Applet 新窗口也随之关闭。

网页弹出一个窗口,是大家经常遇到的情况。为什么司空见惯的 小错误,对于 Java Applet 来说,却是不可容忍的大错呢?原因在于这样的做法,导致浏览器仅仅成为用户接触 Java Applet 的通道,一旦 Java Applet 的窗口打开了,浏览器本身就显得无足轻重。值得关注的观点是,用户接受并且喜爱浏览器的界面,他们不欢迎 Java Applet 把浏览器矮化成通道的做法,他们尤其不欢迎 Java Applet 的 UI 风格看起来和浏览器的风格不一致。

这个观点隐含的核心命题是,Java Applet 之所以失败,根本原因在于 Java Applet 谋图游离于浏览器母体之外,寻求独立的倾向。

解释 Java Applet 为什么失败的猜想很多,如果这种观点仅仅是众多猜想之一,倒也无足轻重。但是继 Java Applet 之后,Sun 进一步延续和深化让 Java 游离于浏览器母体之外的路线,推出了 Java Web Start(JWS),JWS 是否成功,可以验证这个猜想是否正确。

Java Applet 是内置于浏览器框架中的插件,运行 Java Applet 的 Java 虚拟机是浏览器的一个内部组件。微软的 IE 浏览器,对于 Sun 的 Java 虚拟机,采取非暴力不合作的抵制态度。这个局面导致 Sun 认定,欲大力推广 Java Applet,必先绕开浏览器的制肘。在这种想法驱使下,Sun 推出了 Java Web Start(JWS)技术,以此替代先前的 Java Applet。Java Web Start 把浏览器彻底变成通道,一旦打开 JWS,用户看到的不仅仅是弹出的另一个窗口,而且这个新窗口和浏览器母体没有紧密的联系。不仅 JWS 的 UI 渲 染完全可以用 Java Swing 实现,而且鼠标点击,敲键盘等等一系列事件的捕捉和响应,也完全由 Java Swing 控制,和浏览器无关。

与 Java Applet 的命运类似,JWS 也没有大行其道。批评者认为,失败的根源在于 JWS 的设计理念有缺陷,

1. JWS 的 UI 渲染风格与浏览器不同,同时,JWS 渲染 UI 的速度也比浏览器慢,原因是浏览器直接调用图形函数库,而不需要像 Java 那样,需要经过 JVM 的转手。

关于这一点,笔者多少有点疑虑,JVM 的确会造成运行效率的降低,但是浏览器需要解析 HTML 和 CSS,这个过程同样也会耗费时间。有没有 benchmarks,比较一下渲染相同的页面,JWS 和浏览器各需要多长时间?但是话又说回来,即便 JWS 与浏览器在 UI 渲染的速度方面不相上下,也没 有充足的理由让 JWS 重复浏览器的工作,尤其是当浏览器已经做得足够好,并且已经被用户广泛接受。

2. JWS 游离于浏览器之外,把浏览器仅仅作为 HTTP 数据传输的通道,这样的做法隐含着 IPC 的 overhead。原因是,浏览器和 JWS 运行在两个不同的 进程,浏览器与 JWS 之间的数据传输不可避免地依赖于 Inter Process Communication (IPC),而 IPC 也影响运行效率。

详细说来,JWS 和浏览器这两个进程之间交换数据,是通过 message passing 来实现的。在两个不同进程之间传递数据的过程,原理上很简单,sender 进程把需要传输的数据,逐段复制并存入 CPU 的 register 缓存空间,然后 receiver 进程从 CPU 的 register 读取数据。但是假如 CPU 正在处理其它工作,那么在执行 IPC 之前,首先要暂时中止当前的 工作,等待 IPC 结束后,再继续进行这份工作。在 CPU 中止当前的工作的时候,需要首先把 CPU register 空间里,当前正在处理的数据 (switchframe) 复制一份,缓存起来。当 receiver 读取完数据以后,再把缓存起来的数据 (switchframe),重新移入 CPU register。显而易见,把 CPU register 里的数据复制移出,然后再重新移入,是需要消耗资源的,这就是所谓不同进程之间的 IPC,所引发的 context switch 的代价。

3. 对于 JWS 的批评,并不是针对 Java 本身。相反,批评者们认为,Java 和浏览器是天生班配的一对,应该取长补短,相得益彰,而不是试图取代对方。说得具体点,

a. 让浏览器专注于 UI 的渲染工作,以及鼠标点击和键盘输入等等事件的捕捉。

b. 让 Java 专注于数据逻辑的处理。

c. 系统架构方面,不应该以渲染机为中心,把 Java 作为插件。应该让 Java 承担起浏览器的整体控制工作,而渲染机作为浏览器的一个模块,负责 UI 绘制和事件捕捉。

d. 丰富 Java 对于 HTML DOM object 的处理功能,换而言之,所有今日 JavaScript 有关 HTML DOM 的 APIs,Java 都必须实现。

4. Sun Microsystem 不应该因为商务上的受挫,就愤然让 Java 背离浏览器。Java 与浏览器,或者更准确地讲,Java 与渲染机,合则两利,分则两伤。HotJava 浏览器本来有远大前途,raner 浅尝辄止,实在可惜。

Browser War I and II Figure 2. Browser War I and II

回到标题的话题,有一种观点认为,需要不需要 JavaScript, 取决于有没有更好的替代品出现。JavaScript 的原罪在于它是一个文本格式的脚本语言,对于文本格式的脚本语言,要么当场逐句解析,要么当场 JIT 编译,无论如何,性能都不会超越预先编译。JavaScript 的兴起,在于 Java Applet 的没落。Java Applet 之所以没落,是因为没有与 HTML-DOM 紧密关联。JavaScript 之所以成功,并不在于这个语言的内核有多少优势,而是在于它提供了 简洁方便的操控 HTML-DOM 的 APIs。如果对于 Java Applet 加以改造,丰富其操控 HTML-DOM 的 APIs,则 Java Applet 不一定没落,因之,JavaScript 也未必会兴起。

从这个观点出发,浏览器需要重构。与第一代和第二代浏览器不同,新一代浏览器不再以 WebKit 之类渲染机为中心,而是以 Java-DOM 操控为中心,渲染机为专项功能。在新一代浏览器中,本质上不需要 JavaScript 的存在,除非需要反向兼容老旧的含有 JS 的网页。

所谓第一代和第二代浏览器,并没有严格划分。1989 年,欧洲原子能研究组织(CERN)的一名合同工,牛津大学的毕业生 Tim Berners-Lee,提出了用 HTTP 协议构筑万维网(World Wide Web)的设想。1993 年,美国国立超级计算应用中心(NCSA)开发了 Mosaic 浏览器,并被广为接受,从而拉开了第一次浏览器大战的序幕。继承 Mosaic 的衣钵而发展起来的 Netscape 浏览器,曾经辉煌一时,1996 年占据了 90% 左右的市场份额。可惜好景不长,1995 年微软决定开发 IE 浏览器,到了 1997 年,IE 的竞争势头已经锐不可挡,到了 2003 年,Netscape 大势已去,第一次浏览器大战就此结束,以微软 IE 浏览器完胜 而告终。Mosaic,Netscape 以及 IE 的 6.0 以前诸版本,还有史前的其它浏览器,通常被称为第一代浏览器。

自 2003 年以后,Mozilla Firefox,Apple Safari,Opera,以及 2008 年问世的 Google Chrome,纷纷挑战微软 IE,蚕食其市场份额。虽然从技术上讲,这些新兴的浏览器的确比 IE 有一些进步,但是技术上的局部优势,并没有大规模地吸引 IE 的用户。

前面提到的观点,可以说是浏览器领域激进派的看法。他们认为,小修小补颠覆不了 IE 的霸主地位。根本的 解决办法,是重构浏览器,大幅度提高浏览器的性能,使之能够从容地处理更加复杂的计算逻辑,譬如 Visio 那样绘图功能,或者大计算量的网络游戏。只有这 样,才能争夺那些习惯于使用 IE 的用户。

笔者认为,PC 上的浏览器,历史包袱沉重,要冲击现有浏览器的架构设计,估计困难重重。但是手机浏览器还处于诸侯混战之中,没有太多历史积淀。或许这是一个轻装上阵,试一试新一代浏览器的良好突破口。

登录,参与讨论前请先登录

评论在审核通过后将对所有人可见

正在加载中

移动互联网的围观者、起哄者、以及肇事者。

本篇来自栏目

解锁订阅模式,获得更多专属优质内容