狠狠撸
Submit Search
理解础箩补虫性能
?
2 likes
?
1,087 views
kaven yan
Follow
《高性能网站建设进阶指南(Even Faster Websites)》的第一章,作者Douglas Crockford
Read less
Read more
1 of 6
Download now
Download to read offline
More Related Content
理解础箩补虫性能
1.
第1章
理解 Ajax 性能 Understanding Ajax Performance Douglas Crockford 过早的优化是万恶之源。 ——Donald Knuth(译注 1) 1.1 权衡 Trade-offs 设计和构造计算机程序要经过成千上万次抉择,每一次都代表着一种权衡。在进行重大抉 择时,每个选择都有其显著的优缺点,让人难以取舍。我们都期望收益最大化,损耗最小 化。或许,人生的终极权衡是: 我想去天堂,但我不想死。 然而现实情况往往是: 时间、质量和成本,三选二。 这个项目三角形(Project Triangle) (译注 2)说明:即使在最理想的情况下,多快好省的事 也基本不存在,所以权衡无处不在。 计算机程序中,选择算法要权衡运行时间和内存,会为抢占市场而牺牲代码质量。这些权 衡对增量式开发(译注 3)的最终效果影响巨大。 译注 1:此语出自 Donald Knuth 在 1974 发表的 《Structured Programming with Goto Statements》 (http:// pplab.snu.ac.kr/courses/adv_pl05/papers/p261-knuth.pdf)中说“忘记那些微不足道的性能提升 吧, 97%的情况下, 过早的优化是万恶之源。 但我们不应该错过那关键的 3%”。 Donald Knuth 的中文名叫高德纳,他被誉为现代计算机科学的鼻祖,其巨著《计算机程序设计艺术》被誉 为计算机科学界的“圣经”。更多信息请参阅 http://zh.wikipedia.org/wiki/高德纳。 译注 2:它是工程中的一种项目三角模型,快是指交付产物的时间,好是指最终产物的质量,便宜 是指设计和生产产物的成本。更多内容请看 http://en.wikipedia.org/wiki/Project_triangle。项 目三角形容易和项目管理三角形混淆(Project management triangle) ,后者中三个角分别是 时间、 成本和范围, 更多内容请看 http://en.wikipedia.org/wiki /Project_management_triangle。 译注 3:增量式开发(incremental development) ,是一种任务调度和分阶段策略,系统的各个部 分以不同的时间和速度进行开发,完成之后进行整合。它并不强调是否采用迭代式开发 和瀑布式开发这两种再加工策略。取代递增式开发的另一个选择是使用大爆炸集成方式 (big bang integration)来开发整个系统。更多内容请看:http://en.wikipedia.org/wiki/ Iterative_and_incremental_development。 1
2.
每一次接触代码,我们都在权衡改善代码质量和避免产生 Bug 的可能性。关注程序性能时, 我们必须反复斟酌所有权衡因素。 1.2
优化原则 Principles of Optimization 优化的目的是希望降低程序的整体开销。虽然在程序中有许多因素可以优化,但通常人们 会认为这个开销就是程序的执行时间。其实我们更应该把重点放在对程序整体开销影响最 大的那部分。 例如,假设我们通过性能分析得到程序的 4 个模块的开销: 模块 A B C D 开销 54% 4% 30% 12% 即使能以某种方式将模块 B 的开销减少一半,其实也仅降低了整体开销的 2%。如果能将模 块 A 的开销减少 10%,却会得到更好的效果。所以优化那些开销不大的组件收效甚微。 分析应用程序和分析算法密切相关。仔细观察程序的执行时间后,我们会发现其大部分时 间都消耗在循环上。所以,优化那些只执行一次的代码得到的回报微不足道,但优化内部 循环的好处却能达到立杆见影的效果。 例如,若循环的开销和迭代次数成线性关系,那么我们则可以用 O(n)来表示,其性能曲线 如图 1-1 所示。 图 1-1:循环性能 每次迭代的执行时间反映在线段的斜度上:开销越大,斜度越陡。循环的固定开销决定了 起点的高度,但减少固定开销通常没有什么好处。有时,如果能减少每次增量的开销,即 便固定开销有所增加也是有益的。这可能是一个很好的权衡。 另外,在执行时间上有 3 条错误轴线,我们的时间线不能和它们相交(见图 1-2)。第 1 条 是低效线,与之相交会降低用户的关注度,并使用户烦躁不安。第 2 条是受挫线,与之相 交则意味着用户会意识到自己在被迫等待,这会导致他开始考虑其他的事情,比如试试其 2 │ 第 1 章:理解 Ajax 性能
3.
他的 Web 应用程序——包括我们竞争对手的产物。第
3 条线是失败线,这是指由于应用崩 溃或浏览器自己产生一个对话框,告诉用户应用失败需要采取行动,这时用户只好刷新或 关闭浏览器。 图 1-2:错误轴线 避免与错误轴线相交有 3 种方法:减少每次迭代的开销、减少迭代的次数或重新设计应用 程序。 循环嵌套越多,可优化的选择越少。如果循环的开销是 O(n log n)、O(n2)或更糟,减少每 次迭代的时间没有任何效果(见图 1-3) 。唯一有效的选择是减少 n 或更换算法,只有在 n 非常小时,调整每次迭代的开销才会有效果。 图 1-3:嵌套循环的性能 必须正确地设计程序。如果程序不符合要求,即使它速度很快也没什么意义。无论如何, 尽早在开发周期中测试程序是否有性能问题非常重要。在测试 Web 应用时,尽可能模仿真 1.2 优化原则 │ 3
4.
实的用户环境,使用低端机器和低速网络来测试,因为在开发人员的高配置环境中得出的 测试结果很可能会掩盖性能问题。 1.3
Ajax 重构代码能明显降低其复杂性,所以对代码进行优化和其他修改更易产生效益。例如,依 据 YSlow 规则来重构代码会对网页的加载时间产生巨大影响(参见 http://developer.yahoo. com/yslow/) 。 即便如此,由于网页的大小和复杂性,要想把 Web 应用控制在低效线之下还是非常困难。 网页通常内容多、代码量大且组成部分众多,在这之间的跳转会带来巨大的开销。因此对 于连续页面之间差别很小的应用而言,使用 Ajax 技术能带来显著的改善。 传统方式下用户操作的结果是请求替换页面,而 Ajax 的实现方式是:发送数据包到服务端 (通常编码为 JSON 文本) ,然后服务端返回另一个数据包(也是典型的 JSON 编码)来响 应,最后 JavaScript 程序使用这些数据来更新浏览器的显示。这样做,数据的传输量、用户 操作和可视化反馈的时间间隔都明显减少,服务器和浏览器需要做的工作量也减少了。不 幸的是,Ajax 程序员需要做的工作量很可能因此而增加。这也是需要权衡的因素之一。 Ajax 应用的架构明显不同于大多数其他类型的应用,因为它是两个系统共有的。如果想通 过 Ajax 方法对性能有积极的影响,采取正确的分工至关重要。数据包应该尽可能地小。应 用程序应构建成浏览器端和服务端的会话,这两个部分之间用一种简单且富于表达能力的 共用语言进行交流。实时数据传输的方式能让应用在浏览器端保持较小的 n 值,这有助于 循环持续快速运行。 Ajax 应用的常见错误是把所有应用数据都发送给浏览器,这会再次引入 Ajax 本应避免的延 迟问题。这类错误也会增加浏览器需要处理的数据量,增大 n 值,从而更加降低性能。 1.4 浏览器 Browser 浏览器并非为应用平台而设计,因此编写 Ajax 应用程序极具挑战性。脚本语言和文档对象 模型(DOM)原本只设计为支持由简单表单所组成的应用。令人惊讶的是,浏览器已具有 足够的能力可能去实现复杂的应用,但不幸的是,它并未达到一切令人满意的地步,所以 4 │ 第 1 章:理解 Ajax 性能
5.
难度真地非常高。 使用
Ajax 库 (例如 http://developer.yahoo.com/yui/)能缓解这种情况。Ajax 库能充分发挥 JavaScript 的表达能力把 DOM 提升到实用的水平,同时修复令应用无法在各 个品牌浏览器中顺利运行的诸多障碍。 很不幸, DOM API 非常低效且令人费解。 运行程序的最大开销往往是 DOM 而非 JavaScript。 在 Velocity 2008 大会(译注 4)上,Microsoft Internet Explorer 8 团队就打开 Alexa 排名前 100 名的网站页面的时间消耗做了一次性能数据分享(译注 5) (注 1) 。 活动 布局 渲染 HTML 调度 DOM 格式化 JScript 其他 开销 43.16% 27.25% 2.81% 7.34% 5.05% 8.66% 3.23% 2.5% 相比浏览器在其他事情上消耗的时间,运行 JavaScript 的开销是微不足道的。微软团队也提 供了一个更能说明问题的 Ajax 应用示例:一个 email 进程的打开过程时间消耗的数据如下: 活动 布局 渲染 HTML 调度 DOM 格式化 JScript 其他 开销 9.41% 9.21% 1.57% 7.85% 12.47% 38.97% 14.43% 3.72% 脚本的开销依旧低于 15%,而处理 CSS 是最大的开销。即使你能像超人一样使脚本的速度 提升一倍,用户也很难注意到。因此毫无疑问,理解 DOM 的奥秘并减少它的影响比试图给 脚本提速效果更好。 1.5 哇! Wow! 应用程序设计者趋向于在 Ajax 应用中添加酷炫特效。这样做是为了引起类似这样的反响: “哇!我不知道浏览器可以做到这个。 ”当使用不当时,这些酷炫的特性会由于分散用户的 注意力或强迫用户等待连续动画播放完毕从而降低他们的生产效率。误用酷炫特性也会导 致不必要的 DOM 操作,从而带来令人吃惊的巨大开销。 酷炫特效应该只在确实能改善用户体验时才使用,而不应用于炫耀或弥补功能与可用性上 的缺陷。 设计浏览器能胜任的事情。例如,在无限滚动的列表中查看数据库要浏览器存储并展示一 译注 4: Velocity 是由 O'Reilly 主办的一个旨在推进建设更好的互联网的会议,每年举行一次。 内容包括如何给网页提速、如何构建高效可伸缩的基础设施、如何建立可靠的网站和服 务等。Velocity 2008 的详情见 http://en.oreilly.com/velocity2008/public/content/about。 译注 5: 原文给出的相关链接 http://en.oreilly.com/velocity2008/public/schedule/detail/3290 中该主 题 “What's Coming in IE8”的幻灯片地址失效,但你可以通过 http://www.slideshare.net/ techdude/ie8-whats-coming 看到它。 注 1: http://en.oreilly.com/velocity2008/public/schedule/detail/3290。 1.5 哇! │ 5
6.
个非常大的数据集,这就超出了它的有效管理能力。更好的方法是根本无需滚动而采用有 效的分页展示,反而能提供更好的性能且更易用。 1.6 JavaScript 大部分 JavaScript
引擎的优化是为了快速抢占市场而不是性能,所以 JavaScript 一直很自然 地被认为是瓶颈。但通常情况下,瓶颈不是 JavaScript 而是 DOM,所以捣腾脚本收效甚微。 尽量避免捣腾脚本,要正确并清晰地编写程序。捣腾往往越整越乱,它只会让程序更容易 产生 Bug。 幸运的是,竞争压力迫使浏览器制造商改进他们的 JavaScript 引擎的效率。这些改进将激起 浏览器中新型应用的开发热潮。 避免使用那些传说中能让程序更快的奇技淫巧,除非你能证明它们将给应用带来明显的质 量提升。大多数情况下,它们只会降低代码质量,而不会有多大提升。不要纠结于特定浏 览器的怪癖,浏览器仍在发展,最终会支持更好的编码实践。 如果感觉必须捣腾,首先要评估。我们对程序真正开销的直觉往往是错的。只有通过评估, 才能有把握对性能产生积极的影响。 1.7 总结 Summary 一切都是权衡。当我们做性能优化时,不要浪费时间去尝试为那些不消耗大量时间的代码 提速。评估优先,拒绝任何不能提供良好效益的优化。 浏览器通常在运行 JavaScript 上花费的时间很少,绝大部分时间消耗在 DOM 上。你可以要 求浏览器制造商提供更好的性能评估工具。 为质量编程。简洁、易读且条理分明的代码更易于正确理解、维护和优化。避免耍小聪明, 除非可以证明它们能大幅提升性能。 善加利用 Ajax 技术能使应用程序运行得更快,用好它的关键是在浏览器和服务器之间建立 平衡。Ajax 提供了取代页面替换的有效方案,使浏览器成为强大的应用平台,但它并不能 保证这样做就一定会成功。浏览器平台非常具有挑战性,而你对于性能的直觉并不那么可 靠。接下来的章节将帮助你理解如何制作更快的网站。 6 │ 第 1 章:理解 Ajax 性能
Download