提高代码性能技巧谈—以创建千行表格为例

微软的开发周期中很重要的一块是调整产品的性能。性能调整也是开发者应当留心的关键部分之一。 经过多年发展,业界对于如何优化Win32程序性能已经有非常多的了解。

现在开发者遇到的问题之一是不太清楚是什么导致DTHML和HTML页面运行快或者慢。当然,有一些很简单的方法——比如不要使用2MB大的图片。我们曾经使用过另外一些有趣的技巧提高了DHTML页面的性能,希望它们能帮助你改善自己的页面性能。

这里我使用了一个建立Table的程序例子。其中用document.createElement()和element.insertBefore()方法创建了1000行(Row)的表(Table)。每行有一列(Cell)。Cell中包含的内容称为"Text"。这段代码能有多糟呢?这么小的程序又能有多大调整余地呢?请看介绍。

一开始我写了一段自认为会很快的程序,我尽量避免一些低级问题----像没有显式定义变量、或者在一个页面中同时使用VBScript和Javascript。程序如下:

<html>
<body>
<script>
var tbl, tbody, tr, td, text, i, max;
max = 1000;

tbl = document.createElement("TABLE");
tbl.border = "1";
tbody = document.createElement("TBODY");
tbl.insertBefore(tbody, null);
document.body.insertBefore(tbl, null);
for (i=0; i<max; i++) {
tr = document.createElement("TR");
td = document.createElement("TD");
text = document.createTextNode("Text");
td.insertBefore(text, null);
tr.insertBefore(td, null);
tbody.insertBefore(tr, null);
}
</script>
</body>
</html>

在PII233/64MB内存/NT4.0/IE5.0的机器上运行这段程序。页面从本机上装载。从开始装载页面到页面完全安静下来(所有的事件均已经运行,屏幕显示完成)的时间为2328毫秒,这也是本次测试的基线(我称之为Test1)。

这个页面中,一个很耗时的操作是频繁引用全局对象,如“document”、“body”、“window”等。引用所有这些类似的全局变量远比引用一个本地变量代价高昂。

因此我作了第一次改进尝试:缓存(Cache)document.body 到本地变量“theBody”中:

增加了如下代码:

var theBody = document.body;
然后修改这一行:

document.body.insertBefore(tbl, null);
将之改为:

theBody.insertBefore(tbl, null);
View the second sample.

这次修改并没有太大影响到整体时间,它只缩短了3 ms。但它已经表明,如果在循环中也有document.body对象而对其引用做出修改,带来的好处将是可观的。

随后,我缓存了document对象----在我们这个测试中,document对象共被引用了3002次。修改后代码如下:

<html>
<body>
<script>
var tbl, tbody, tr, td, text, i, max;
max = 1000;
var theDoc = document;
var theBody = theDoc.body;

tbl = theDoc.createElement("TABLE");
tbl.border = "1";
tbody = theDoc.createElement("TBODY");
tbl.insertBefore(tbody, null);
theBody.insertBefore(tbl, null);
for (i=0; i<max; i++) {
tr = theDoc.createElement("TR");
td = theDoc.createElement("TD");
text = theDoc.createTextNode("Text");
td.insertBefore(text, null);
tr.insertBefore(td, null);
tbody.insertBefore(tr, null);
}
</script>
</body>
</html>
View the third sample.

此次运行时间只有2100ms,节约了大约10%的时间。使用本地变量而不是直接引用document对象平均每次节约了0.4毫秒。

一个常用的优化性能的方法是:当脚本不需要立即运行时,在<SCRIPT>标签中设置“defer”属性。 (立即脚本没有被包含在一个function块中,因此会在加载过程中执行。) 设置“defer”属性后,IE就不必等待该脚本装载和执行完毕。这样页面加载会更快。一般来说,这也表明立即脚本最好放在function块中,并在document或者body对象的onload 句柄中处理该函数。在有一些脚本需要依赖用户操作而执行时----例如点击按钮,或者移动鼠标到某个区域----使用该属性非常有用。但当有一些脚本需要在页面加载过程中或加载完成后执行,使用defer属性得到的好处就不太大。

下面是使用了defer属性修改后的代码版本:

<html>
<body onload="init()">
<script defer>
function init() {
var tbl, tbody, tr, td, text, i, max;
max = 1000;
var theDoc = document;
var theBody = theDoc.body;

tbl = theDoc.createElement("TABLE");
tbl.border = "1";
tbody = theDoc.createElement("TBODY");
tbl.insertBefore(tbody, null);
theBody.insertBefore(tbl, null);
for (i=0; i<max; i++) {
tr = theDoc.createElement("TR");
td = theDoc.createElement("TD");
text = theDoc.createTextNode("Text");
td.insertBefore(text, null);
tr.insertBefore(td, null);
tbody.insertBefore(tr, null);
}
}
</script>
</body>
</html>
View the fourth sample.

这次测试的时间为2043 ms。相对基线测试提高了12%,比上次测试提高了2.5%。

下面我们谈到的一个改进方法非常有用,当然也稍微麻烦一点。当需要创建元素然后将其插入树状的结构中时,将其直接插入到主干中效率更高----而不是首先将其插入大的子树,然后再将大的子树插入主干。例如,如果你创建一个每行有一列、列中有一些文字的表,你可以这样做:

1. 创建<TR>

2. 创建<TD>

3. 创建TextNode节点

4. 将TextNode 插入<TD>

5. 将<TD> 插入到 <TR>

6. 将<TR>插入到TBODY

当它要比下面的方法慢一些:

1. 创建<TR>

2. 创建<TD>

3. 创建TextNode

4. 将<TR> 插入到TBODY

5. 将<TD> 插入到<TR>

6. 将TextNode插入到<TD>

上面的四次测试使用的都是前一种方法。我们用后一种方法进行第5次测试。代码如下:

<html>
<body onload="init()">
<script defer>
function init() {
var tbl, tbody, tr, td, text, i, max;
max = 1000;
var theDoc = document;
var theBody = theDoc.body;

tbl = theDoc.createElement("TABLE");
tbl.border = "1";
tbody = theDoc.createElement("TBODY");
tbl.insertBefore(tbody, null);
theBody.insertBefore(tbl, null);
for (i=0; i<max; i++) {
tr = theDoc.createElement("TR");
td = theDoc.createElement("TD");
text = theDoc.createTextNode("Text");
tbody.insertBefore(tr, null);
tr.insertBefore(td, null);
td.insertBefore(text, null);
}
}
</script>
</body>
</html>
View the fifth sample.

Test5只需1649ms。这比上次测试提高了25%,比基线快了几乎30%。

随后的修改是使用了预制的样式表。使用了预制样式表的表格列宽或者是通过<COL>标签设置,没有<COL>标签时,每列的宽度均匀分布。因为不需要对每一列重新计算大小等,使用样式表实际上提高了性能,尤其当表格中的列数很多时。

增加样式表(CSS)的代码非常简单,如下:

tbl.style.tableLayout = "fixed";
View the sixth sample.

因为我们测试中的表格只有一列,这种改变只提高了页面1.6%的性能。如果有更多的列,性能增加会更多。

最后两次测试改变了将文字插入到表格中的方法。前面的测试中,我们都先创建一个TextNode ,然后将其插入到TD中。在Test7中, 取而代之,我们通过innerText 指定包含的文字。修改的代码是:

td.innerText = "Text";
View the seventh sample.

令人惊奇的是,这次修改产生的差异很大----比上次提高了9%的性能,比最初总共提高了36%的性能。时间从最初的2323ms到最后的1473ms。

现在,几乎人人都知道使用element.innerHTML 非常慢. 为了看看究竟它如何慢,我做了最后一次测试:使用 innerHTML替代innerText插入文字。这大大降低了性能。时间达到3375ms,比上次测试慢了80%,比基线测试慢了45%。显然,innerHTML是非常耗时的。

调整HTML页面性能类似于调整Win32应用程序性能;需要知道什么慢,什么快。希望这些方法能帮你提高页面性能。

(0)

相关推荐

  • .NET Visual Studio 代码性能分析工具

    下面通过图文并茂的方式给大家介绍下,具体内容如下: 软件开发中的性能优化对程序员来说是一个非常重要的问题.一个小问题可能成为一个大的系统的瓶颈.但是对于程序员来说,通过自身去优化代码是十分困难的.幸运的是,有一些非常棒的工具可以帮助程序员进行代码分析和性能测试,从而大大简化程序员进行代码性能优化的过程.MSDN杂志2011年7月份曾发布主题为".NET代码分析工具和技术"的那一期,让广大程序员收获颇丰.四年过去之后,这些工具又进一步做出了很多改进,同时也出现了更多的选择.本文对当前主流

  • 使用VisualStudio开发php的图文设置方法

    现在,三层.mvc之类的思想遍地开花,使得代码和html得以分离,加之随着开发的分工和项目的增大,一个好的IDE能为编码工作提供了许多的便利.就像开发java用eclipse,.NET用visual studio一样,开发PHP也很需要一种这样的利器.常见的php的IDE有Eclipse,NetBeans,Zend studio,vs.php等.这几个我也都用过,其中Eclipse,NetBeans,Zend studio都有win和linux的版本,也都集成了像代码感知.调试.设计.片段等的功

  • Python 代码性能优化技巧分享

    如何进行 Python 性能优化,是本文探讨的主要问题.本文会涉及常见的代码优化方法,性能优化工具的使用以及如何诊断代码的性能瓶颈等内容,希望可以给 Python 开发人员一定的参考. Python 代码优化常见技巧 代码优化能够让程序运行更快,它是在不改变程序运行结果的情况下使得程序的运行效率更高,根据 80/20 原则,实现程序的重构.优化.扩展以及文档相关的事情通常需要消耗 80% 的工作量.优化通常包含两方面的内容:减小代码的体积,提高代码的运行效率. 改进算法,选择合适的数据结构 一个

  • c# yield提高代码性能和可读性

    对于"yield"这个关键字我已经见过N次了,直到最近我才知道这个关键字所蕴含的力量.我将在下面展示出一些使用"yield"让你的代码有更高可读性和更好性能的例子 为了让你对yield有一些快速概览,我首先要展示一个没有使用这个关键字的例子,下面的代码很简单 复制代码 代码如下: IList<string> FindBobs(IEnumerable<string> names){ var bobs = new List<string&g

  • 提高代码性能技巧谈—以创建千行表格为例

    微软的开发周期中很重要的一块是调整产品的性能.性能调整也是开发者应当留心的关键部分之一. 经过多年发展,业界对于如何优化Win32程序性能已经有非常多的了解. 现在开发者遇到的问题之一是不太清楚是什么导致DTHML和HTML页面运行快或者慢.当然,有一些很简单的方法--比如不要使用2MB大的图片.我们曾经使用过另外一些有趣的技巧提高了DHTML页面的性能,希望它们能帮助你改善自己的页面性能. 这里我使用了一个建立Table的程序例子.其中用document.createElement()和ele

  • C#处理类型和二进制数据转换并提高程序性能

    目录 C# 原语类型 1,利用 Buffer 优化数组性能 2,BinaryPrimitives 细粒度操作字节数组 提高代码安全性 3,BitConverter.MemoryMarshal 4,Marshal 实践 更高性能 C# 原语类型 按照内存分配来区分,C# 有值类型.引用类型: 按照基础类型类型来分,C# 有 内置类型.通用类型.自定义类型.匿名类型.元组类型.CTS类型(通用类型系统): C# 的基础类型包括: 整型: sbyte, byte, short, ushort, int

  • php提高脚本性能的4个技巧

    通常,我使用明显的常规PHP函数编写代码来解决相应的问题.但是对于其中的一些问题,我遇到了一些替代解决方案,这些解决方案特别提高了性能. 在本文中,我想介绍一些替代方案.如果您正在寻找可能减少生产中执行时间的可能性,这将很有用.让我们看看,哪种PHP方法可能会被性能更高的方法所取代,以及是否存在成本或折衷的问题. 1.删除重复项 您有一个包含重复项的大型数组,并且希望删除它们,使其仅具有唯一值的数组. 常规 array_unique($array); 替代 array_keys(array_fl

  • 在DB2中提高INSERT性能的技巧(1)

    正在看的db2教程是:在DB2中提高INSERT性能的技巧(1). INSERT 处理过程概述 首先让我们快速地看看插入一行时的处理步骤.这些步骤中的每一步都有优化的潜力,对此我们在后面会一一讨论. 在客户机准备 语句.对于动态 SQL,在语句执行前就要做这一步,此处的性能是很重要的:对于静态 SQL,这一步的性能实际上关系不大,因为语句的准备是事先完成的. 在客户机,将要插入的行的各个 列值组装起来,发送到 DB2 服务器. DB2 服务器确定将这一行插入到哪一页中. DB2 在 用于该页的缓

  • .Net Core中使用ref和Span<T>提高程序性能的实现代码

    一.前言 其实说到ref,很多同学对它已经有所了解,ref是C# 7.0的一个语言特性,它为开发人员提供了返回本地变量引用和值引用的机制. Span也是建立在ref语法基础上的一个复杂的数据类型,在文章的后半部分,我会有一个例子说明如何使用它. 二.ref关键字 不论是ref还是out关键,都是一种比较难以理解和操作的语言特性,如C语言中操作指针一样,这样的高级语法总是什么带来一些副作用,但是我不认为这有什么,而且不是每一个C#开发者都要对这些内部运行的机制有着深刻的理解,我觉得不论什么复杂的东

  • 提高jQuery性能优化的技巧

    下面把提高jQuery性能优化技巧给大家分享如下: 缓存变量 DOM遍历是昂贵的,所以尽量将会重用的元素缓存. 复制代码 代码如下: // 糟糕 h = $('#element').height(); $('#element').css('height',h-20); // 建议 $element = $('#element'); h = $element.height(); $element.css('height',h-20); 避免全局变量 jQuery与javascript一样,一般来说

  • 值得收藏的9个提高代码运行效率的小技巧(推荐)

    我们写程序的目的就是使它在任何情况下都可以稳定工作.一个运行的很快但是结果错误的程序并没有任何用处.在程序开发和优化的过程中,我们必须考虑代码使用的方式,以及影响它的关键因素.通常,我们必须在程序的简洁性与它的运行速度之间做出权衡.今天我们就来聊一聊如何优化程序的性能. 1. 减小程序计算量 1.1 示例代码 for (i = 0; i < n; i++) { int ni = n*i; for (j = 0; j < n; j++) a[ni + j] = b[j]; } 1.2 分析代码

  • Java 中的5个代码性能提升技巧

    目录 1.预先分配 HashMap 的大小 2.优化 HashMap 的 key 3.不使用 Enum.values() 遍历 4.使用 Enum 代替 String 常量 5.使用高版本 JDK 前言: 提示:我们不应该为了优化而优化,这有时会增加代码的复杂度. 这篇文章中的代码都在以下环境中进行性能测试. JMH version: 1.33(Java 基准测试框架) VM version: JDK 17, OpenJDK 64-Bit Server VM, 17+35-2724 通过这篇文章

随机推荐