性能测试工具
dom操作
测试代码
<div id="domTestWrap">
<div class="dom-test-content">
<span class="dom-test-text"></span>
</div>
<div class="dom-test-content">
<span class="dom-test-text"></span>
</div>
<div class="dom-test-content">
<span class="dom-test-text"></span>
</div>
</div>
function domTestDepthOne () {
document.getElementById('domTestWrap')
}
function domTestDepthOneQS () {
document.querySelector('#domTestWrap')
}
function domTestDepthTwo () {
document.getElementById('domTestWrap').getElementsByClassName('dom-test-content')
}
function domTestDepthTwoQSA () {
document.querySelectorAll('#domTestWrap .dom-test-content')
}
function domTestDepthThree () {
var domTestTextList = document.getElementById('domTestWrap').getElementsByClassName('dom-test-content')
for (var i=0; i< domTestTextList.length; i++) {
domTestTextList[i].innerHTML
}
}
function domTestDepthThreeQSA () {
var domTestTextList = document.querySelectorAll('#domTestWrap .dom-test-content')
for (var i=0; i< domTestTextList.length; i++) {
domTestTextList[i].innerHTML
}
}
JSLitmus.test('dom test depth one', domTestDepthOne)
JSLitmus.test('dom test depth one query selecter', domTestDepthOneQS)
JSLitmus.test('dom test depth two', domTestDepthTwo)
JSLitmus.test('dom test depth two query selecter all', domTestDepthTwoQSA)
JSLitmus.test('dom test depth three query', domTestDepthThree)
JSLitmus.test('dom test depth three query selecter all', domTestDepthThreeQSA)
测试结果
PS:黄条代表每秒可执行测试函数的次数,当然越多越快。
分析总结
dom操作非常耗时,querySelector&querySelectorAll书写方便但相比
document.getElementById更加耗时些。务必减少dom操作,减少无意义的dom路径的查找。
对象操作
测试代码
var objectTest = {
one : {
name: 'one',
value: 1,
two: {
name: 'two',
value: 2,
three: {
name: 'three',
value: 3
}
}
}
}
var three = objectTest.one.two.three;
function objectTestDepthZero () {
three.name
three.value
}
function objectTestDepthThree () {
objectTest.one.two.three.name
objectTest.one.two.three.value
}
JSLitmus.test('object test depth zero', function (count) {
while (count -- ) objectTestDepthZero()
})
JSLitmus.test('object test depth three', function (count) {
while (count -- ) objectTestDepthThree()
})
测试结果
分析总结
对象属性的访问非常耗时,原因于JavaScript引擎内部存储变量的结构有关,JavaScript是弱类型语言,它不像强类型语言如C、C++那样可以通过内存地址偏移来快速访问。
可以参考,用最简单易懂的道理告诉你,为什么JavaScript在现代引擎(V8,JavaScriptCore)下,能表现出卓越性能!
务必减少对象嵌套的深度,减少无意义的对象路径的查找
作用域冒泡
测试代码
测试代码来自JSLitmus官网主页的例子
// 很多开发者不知道变量作用域对于脚本的性能有多少影响。
// 为了直观地展示这一点,我们写了下面的JSLitmus测试用例去测量对定义在不同作用域下的变量
// 执行"递增(++)"操作的表现
// 首先,测试定义在全局作用域的变量
var global_var = 1;
JSLitmus.test('global', function(count) {
while (count--) global_var++;}
);
// 现在测试一个定义在局部函数作用域的变量
JSLitmus.test('local', function(count) {
var local_var = 1;
while (count--) local_var++;
});
// 尝试测试一个绑定到立即执行函数内的变量。
// 喜欢Prototype和JQuery的开发者应该觉得这样特别有意思
JSLitmus.test('closure',
(function() {
var closure_var = 1;
return function(count) {while (count--) closure_var++;}
})()
);
// 还是绑定在立即执行函数中的变量,不过这次套了两层
JSLitmus.test('multi-closure',
(function() {
var multi_var = 1;
return (function() {
return function(count) {while (count--) multi_var++;}
})()
})()
);
// 测试一个空的函数调用,这可以作为一个参照点
JSLitmus.test('empty function call', function(count) {
var f = function() {};
while (count--) f();
});
测试结果
分析总结
每次访问变量或者函数都会进行一次作用域冒泡的过程,所以本地作用域如函数作用域是最快的,全局作用域最慢。
应该要尽量减少这个冒泡的层数,对于要经常访问的全局变量,应该在本地作用域做一个缓存。
其他测试
测试代码
这些测试代码来自,JSLitmus官网的例子
// 这是一个空的非循环测试。它的结果应该是一秒可以做无限次,或者非常接近无限的一个值
JSLitmus.test('empty test (non-looping)', function() {});
// 这是一个空的循环测试,对于这种执行非常快的代码,需要执行更多次才能得到比较准确的结果
// 所以经常使用循环测试
// 它的结果应该是一秒可以做无限次,或者非常接近无限的一个值
JSLitmus.test('empty test', function(count) {
while (count--);
});
// 测试调用一个定义在全局作用域的函数的消耗
var emptyFunction = function() {};
JSLitmus.test('function overhead (non-looping)', function() {
emptyFunction();
});
// 循环测试调用一个定义在本地作用域函数的消耗。
// 这个应该比前者更快,一个原因是使用循环测试更准确,另一个原因是函数定义在本地作用域了
JSLitmus.test('function overhead', function(count) {
var f = emptyFunction;
while (count--) f();
});
// 测试Array.join()方法,然后我们可以看看它和字符串"+"操作的对比
JSLitmus.test('"hello" + "world" (non-looping)', function() {
var a = "hello", b = "world", x;
x = a+b;
});
// 循环测试Array.join()方法,然后我们可以看看它和字符串"+"操作的对比
JSLitmus.test('"hello" + "world"', function(count) {
var a = "hello", b = "world", x;
while(count--) x = a+b;
});
// 循环测试Array.join()方法,然后我们可以看看它和字符串"+"操作的对比
JSLitmus.test('string join()', function(count) {
var a = ['hello', 'world'];
while (count--) a.join();
});
// Math.random()是快还是慢呢?
JSLitmus.test('Math.random()', function(count) {
while (count--) Math.random();
});
// 正则表达测试有多快呢?让我们来一探究竟
JSLitmus.test('RegExp.test()', function(count) {
while (count--) /rl/.test('hello world');
});
// 呵呵,如果在循环的外面定义正则表达式对象会有帮助吗?
JSLitmus.test('cached RegExp.test()', function(count) {
var re = /rl/;
while (count--) re.test('hello world');
});
// 新建Date对象的速度怎样?是快还是慢?
JSLitmus.test('new Date()', function(count) {
while (count--) new Date();
});
// 如果我们把Dete对象设置到元素的innerHTML中的速度如何?
// 因为这个操作一定很慢,所以就不需要循环测试了
JSLitmus.test('set Element.innerHTML', function() {
document.getElementById('test_element').innerHTML = new Date();
});
// 测试一个数组的创建,这个可以作为一个参照物
JSLitmus.test('new Array()', function(count) {
while (count--) {var a = [];}
});
测试结果
分析总结
图中,Infinity的测试代表非常快,其中,空函数的调用,字符串的"+"的拼接都非常快。
Math.random()与新建一个数组也比较快。
正则表达式测试,数组的join,新建日期,稍微慢了些。
最后,设置innerHTML的dom操作最慢。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。