当前位置:编程学习 > JAVA >>

提升web应用程序的性能- 找出瓶颈,加快客户端内容的速度

简介: 作为 web 用户,我们知道页面加载或刷新的速度对其成功至关重要。本文将帮助您更好地理解影响 web 应用程序性能的因素。学习识别这些问题并且找到客户端内容的瓶颈。探索 JavaScript、DOM、CSS 和 Dojo 小部件的性能问题。将通过一个例子展示使用 YSlow 和 Firebug 适当调整 Dojo 小部件。
本文的标签:  ajax, dhtml_(dynamic_html), ecmascript, javascript, web, 应用程序的性能, 应用集成, 技巧, 提升
概览
Rich Internet applications (RIAs) 在 Web 2.0 领域非常流行。为了提供新鲜、别致的用户体验,很多网站用 JavaScript 或 Flash 将复杂的内容从后台服务器搬到前台客户端。如果 数据较少的话,这提供了一个方便、新颖,流畅的用户界面(UI)。如果要将大量内容从服务器转移到客户端并在浏览器呈现,性能将显著下降。挑战是找到瓶颈,确定解决方案。
在浏览器中调整性能问题比在 Java 应用程序中更难。开发人员在各种浏览器中调试 JavaScript 的方法要少得多。在 Mozilla Firefox 中,可以使用 Firebug 调试 JavaScript,但仍然不能调整很多性能问题,如浏览器呈现消耗时间。为了解决这些问题,有必要开发浏览器插件来监控时间响应,以及确定其他对应解 决方案如部分呈现或延时加载。
学习诊断 web 应用程序中的性能问题,找到客户端内容中的瓶颈,并调整性能。
JavaScript 和 HTML DOM
JavaScript 是用在 Internet 上的最流行的脚本语言。数以万计的 web 页面设计师使用 JavaScript 来改善设计、验证表单、检查浏览器以及创建 cookie。HTML Document Object Model (DOM) 定义了访问和操作 HTML 文档的标准方法。它将 HTML 文档表示成节点树,其中包含元素、属性和文本内容。
通过使用 HTML DOM,JavaScript 能访问 HTML 文档中所有节点并操作它们。很多主流浏览器都支持 JavaScript 和 HTML DOM,而且很多网站也使用它们。它们使用的性能显著影响到整个 RIAs 的性能。
JavaScript 性能和函数
在 JavaScript 中,当需要某一功能时,使用 函数。尽管有些情形下可以用字符串代替函数,我们还是建议您尽可能使用函数。在 JavaScript 中,函数在使用前会预编译。
例如,看 清单 1 中的 eval 方法。
清单 1. eval 方法用字符串作参数
function square(input) {
  var output;
  eval('output=(input * input)');
  return output;
}
eval 方法计算平方值并输出结果,但性能不好。此例使用字符串 output=(input*input) 作为 eval 方法的参数,无法利用 JavaScript 预编译。
清单 2 显示了一个完成此任务的更好的方法。
清单 2. 使用函数作参数的 Eval 方法
function square(input) {
  var output;
  eval(new function() { output=(input * input)});
  return output;
}
使用函数代替字符串作参数确保新方法中的代码能被 JavaScript 编译器优化。
函数作用域
JavaScript 函数作用域链中的每个作用域都包含几个变量。理解作用域链很重要,这样才能利用它。清单 3 显示的是一个函数作用域样例。
清单 3. 函数作用域
function test() {
  var localVar = “test”;
  test1(this. localVar);
var pageName = document.getElementById(“pageName”);
}
图 1 显示了作用域链结构。

图 1. 作用域链结构

理解作用域链的结构对利用它很重要

使用局部变量比使用全局变量快得多,因为在作用域链中越远,解析越慢。
如果代码中有 with 或 try-catch 语句,作用域链会更复杂。图 2 显示的是 try-catch 语句的作用域链。
图 2. Try-catch 作用域链结构

作用域链中的 try-catch 语句使其更加复杂

字符串函数
JavaScript 中最不可取的函数是字符串连接。我通常使用 + 号来实现连接。清单 4 显示了一个此类样例。
清单 4. 字符串连接
var txt = “hello” + “ ” + “world”;
这条语句创建了几个包含连接结果的中间字符串。这样在后台连续创建和销毁字符串导致极低的字符串连接性能。早期的浏览器对这样的操作没有优化。我们建议您创建一个 StringBuffer 类来实现,如 清单 5 所示。
清单 5. StringBuffer 对象
 
function StringBuffer() {
this.buffer = [];
}

StringBuffer.prototype.append = function append(val) {
 this.buffer.push(val);
 return this;
}

StringBuffer.prototype.toString = function toString () {
 return this.buffer.join(“”);
}
对字符串对象(而非值)定义了所有的属性和方法。当您引用一个字符串值的属性或方法时,ECMAScript 引擎在方法执行前隐式创建一个具有相同值的新字符串对象。此对象只用于特定请求,当下一次使用字符串值的方法时重新创建。
这种情况下,对那些方法会被调用多次的字符串使用新的语句。
新字符串对象的例子如 清单 6 所示。
清单 6. 创建新字符串对象的例
var str = new String(“hello”);
StringObject.indexOf 比 StringObject.match 快。当搜索简单字符串匹配时,尽可能用 indexOf 而不用正则表达式匹配。
尽量避免在长字符串中匹配(10KB 及以上),除非您别无选择。如果您确定只在字符串某一特定部分匹配,用子串而不是整个字符串比较。
DOM 性能
本章简要介绍了一些可进行调整以提升 DOM 性能的内容。
重绘(Repaint)
当之前不可见的内容变得可见,DOM 就会重绘,反过来也一样。重绘也称为重画。此行为不会改变文档布局。不改变元素尺寸、形状或位置,只改变外观也会触发重绘。
例如,给元素添加边框或改变背景色就会触发重绘。重绘的性能代价很大;它需要引擎搜索所有元素以确定哪些可见,哪些必须显示。
回流(Reflow)
回流是比重绘更显著的改变。在回流中:
要操作 DOM 树。
影响布局的样式会改变。
元素的 className 属性会改变。
浏览器窗口尺寸改变。
引擎将会对相关元素回流,以确定各部分显示在哪。子元素也会被回流以反映父元素的新布局。DOM 中元素后面的元素也会被回流,以计算新布局,因为它们可能在初始回流时被移动了。祖先元素也会因子孙元素大小变化而被回流。最后,所有内容都被重绘。
每次向文档添加一个元素,浏览器都要回流页面来计算所有内容如何定位、如何呈现。添加的东西越多,回流次数越多。如果能减少单独添加元素的次数,浏览器回流次数就更少,运行也更快。
CSS 性能
将 Cascading Style Sheets (CSS) 放在顶端。如果样式表放在底部,将最后加载。之前几秒钟,页面都是空白,浏览器等待样式表加载,然后页面上其他东西才能呈现 — 甚至是静态文本。
在 Internet Explorer 中,@import 与在底部使用 <link> 效果一样。我们建议您不要使用。
缩写属性
使用缩写属性在一个声明中一次设置几个属性,而不是每个属性用一个声明。使用缩写属性,可以减小文件大小,降低维护量。
例如,可以设置背景、边框、边框颜色、边框样式、边框侧(顶部边框、右侧边框、底部边框、左侧边框)、边框宽度、字体、页边距、轮廓、填充属性。
CSS 选择器
CSS 选择器通过从右到左 移动来匹配。清单 7 所示,浏览器必须遍历页面中每个锚元素以确定它的父元素 ID 是否是 aElement。
清单 7. 选择器正从右到左匹配
#aElement > a{
    font-size: 18px;
}
如果从代码中移除 > ,如 清单 8 所示,性能更糟。浏览器要检查整个文档中的所有锚。这样就不是只检查锚的父元素,而是顺着文档树向上查找 ID 为 aElement 的祖先元素。如果正在检查的元素不是 aElement 的子孙,浏览器就要沿着祖先元素的树查找,直到文档根部。
清单 8. 如果没有 >,性能更糟
#aElement a{
    font-size: 18px;
}
最佳实践
本章将略述能帮助您提升 web 应用程序性能的最佳实践。
减少 HTTP 请求数
每个 HTTP 请求都有开销,包括查找 DNS、创建连接及等待响应,因此削减不必要的请求数可减少不必要的开销。要减少请求数:
合并文件。将总是同时使用的脚本合并到同一个文件中,不会减小总大小,但将会 减少请求数。还可以同样方法合并 CSS 文件和图片。可以实现文件自动合并:
在构建阶段。用 <concat > 标记,通过运行 Ant 合并文件。
在运行时阶段。启用 mod_concat 模块。如果 httpServer 是 Apache,用 pack:Tag 作为 JSP 标签库来合并 JavaScript 和样式表文件。(pack:Tag 是一个 JSP-Taglib,可缩减、压缩及合并资源,如 JavaScript 和 CSS,并将它们在内容或普通文件中缓存。)
使用 CSS Sprites。将背景图片合并成一个图片,并使用 CSS background-image 和 background-position 属性来显示所需图片部分。还可使用内联图片减少请求数。
后置加载组件
只呈现需要的组件;其余可等待。最好不要一次呈现太多组件。
某些情况下,可使用后置加载。由于浏览器可视区域外的组件可以后置加载,

补充:web前端 , JavaScript ,
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,