![](/img/trans.png)
[英]How do you test regular JavaScript code that does not export anything?
[英]How do you performance test JavaScript code?
CPU 周期、Memory 使用情况、执行时间等?
补充:JavaScript 中除了感知代码运行速度之外,是否有定量的方法来测试性能?
探查器绝对是获取数字的好方法,但根据我的经验,感知性能对用户/客户来说是最重要的。 例如,我们有一个带有 Ext 手风琴的项目,它可以扩展以显示一些数据,然后是一些嵌套的 Ext 网格。 一切其实都渲染得很快,没有一个操作需要很长时间,只是一次渲染了很多信息,所以用户感觉很慢。
我们“修复”了这个问题,不是通过切换到更快的组件或优化某些方法,而是通过先渲染数据,然后使用 setTimeout 渲染网格。 因此,信息首先出现,然后网格会在下一秒后弹出。 总的来说,这样做需要更多的处理时间,但对用户来说,感知性能得到了改善。
如今,Chrome 分析器和其他工具普遍可用且易于使用, console.time()
、 console.profile()
和performance.now()
。 Chrome 还为您提供了一个时间线视图,它可以向您显示导致您的帧速率下降的因素、用户可能正在等待的位置等。
查找所有这些工具的文档非常简单,您不需要为此提供 SO 答案。 7 年后,我仍然会重复我原来的答案的建议,并指出你可以让缓慢的代码在用户不会注意到的地方永远运行,而在他们所做的地方运行非常快的代码,他们会抱怨相当快的代码不够快。 或者您对服务器 API 的请求花费了 220 毫秒。 或者其他类似的东西。 重点仍然是,如果你拿出一个分析器去寻找工作要做,你会找到它,但它可能不是你的用户需要的工作。
我确实同意感知性能真的很重要。 但有时我只想找出做某事的哪种方法更快。 有时差异是巨大的,值得了解。
你可以只使用 javascript 计时器。 但我通常使用原生 Chrome(现在也在 Firefox 和 Safari 中)devTool 方法console.time()
& console.timeEnd()
获得更一致的结果
var iterations = 1000000;
console.time('Function #1');
for(var i = 0; i < iterations; i++ ){
functionOne();
};
console.timeEnd('Function #1')
console.time('Function #2');
for(var i = 0; i < iterations; i++ ){
functionTwo();
};
console.timeEnd('Function #2')
Chrome canary 最近添加了Line Level Profiling the dev tools sources 选项卡,让您准确了解每行执行所需的时间!
我们总是可以通过简单的日期对象来测量任何函数所花费的时间。
var start = +new Date(); // log start timestamp
function1();
var end = +new Date(); // log end timestamp
var diff = end - start;
试试jsPerf 。 它是一个在线 javascript 性能工具,用于对代码片段进行基准测试和比较。 我用它所有的时间。
大多数浏览器现在在performance.now()
实现高分辨率计时。 它在性能测试方面优于new Date()
,因为它独立于系统时钟运行。
用法
var start = performance.now();
// code being timed...
var duration = performance.now() - start;
参考
JSlitmus是一个轻量级的工具,用于创建特别的 JavaScript 基准测试
让我们检查function expression
和function constructor
之间的性能:
<script src="JSLitmus.js"></script>
<script>
JSLitmus.test("new Function ... ", function() {
return new Function("for(var i=0; i<100; i++) {}");
});
JSLitmus.test("function() ...", function() {
return (function() { for(var i=0; i<100; i++) {} });
});
</script>
我上面所做的是创建一个执行相同操作的function expression
和function constructor
。 结果如下:
FireFox 性能结果
IE 性能结果
有些人建议使用特定的插件和/或浏览器。 我不会,因为它们只对那个平台真正有用; 在 Firefox 上运行的测试不会准确地转换为 IE7。 考虑到 99.999999% 的网站有多个浏览器访问它们,您需要检查所有流行平台的性能。
我的建议是将其保留在 JS 中。 创建一个包含所有 JS 测试和执行时间的基准测试页面。 您甚至可以使用 AJAX 将结果发回给您,以使其完全自动化。
然后只需冲洗并在不同的平台上重复。
这是一个简单的函数,用于显示传入函数的执行时间:
var perf = function(testName, fn) {
var startTime = new Date().getTime();
fn();
var endTime = new Date().getTime();
console.log(testName + ": " + (endTime - startTime) + "ms");
}
我认为 JavaScript 性能(时间)测试已经足够了。 我在这里找到了一篇关于JavaScript 性能测试的非常方便的文章。
你可以使用这个: http : //getfirebug.com/js.html 。 它有一个用于 JavaScript 的分析器。
performance.mark('initSelect - start');
initSelect();
performance.mark('initSelect - end');
快速回答
在 jQuery(更具体地说是在 Sizzle 上)上,我们使用它(结帐大师并在浏览器上打开 speed/index.html),而后者又使用benchmark.js 。 这用于对库进行性能测试。
长答案
如果读者不知道基准测试、工作负载和分析器之间的区别,请首先阅读spec.org的“自述文件 1”部分中的一些性能测试基础。 这是用于系统测试,但了解此基础也将有助于 JS 性能测试。 一些亮点:
什么是基准?
基准是“测量或评估的标准”(韦氏二词典)。 计算机基准测试通常是一个计算机程序,它执行一组严格定义的操作——工作负载——并返回某种形式的结果——一个度量——描述被测试计算机的执行方式。 计算机基准指标通常衡量速度:工作负载完成的速度; 或吞吐量:每单位时间完成了多少工作负载单元。 在多台计算机上运行相同的计算机基准测试可以进行比较。
我应该对自己的应用程序进行基准测试吗?
理想情况下,系统的最佳比较测试是您自己的应用程序和您自己的工作负载。 不幸的是,使用自己的应用程序和自己的工作负载为不同的系统获得可靠、可重复和可比较的广泛基础通常是不切实际的。 问题可能包括生成好的测试用例、保密问题、难以确保可比较的条件、时间、金钱或其他限制。
如果不是我自己的应用程序,那又是什么?
您可能希望考虑使用标准化基准作为参考点。 理想情况下,标准化的基准测试将是可移植的,并且可能已经在您感兴趣的平台上运行。但是,在考虑结果之前,您需要确保您了解应用程序/计算需求与应用程序/计算需求之间的相关性基准是衡量。 基准测试是否与您运行的应用程序类型相似? 工作负载是否具有相似的特征? 根据您对这些问题的回答,您可以开始了解基准测试如何接近您的实际情况。
注:标准化基准可作为参考点。 尽管如此,当您在进行供应商或产品选择时,SPEC 并不声称任何标准化的基准测试都可以替代您自己的实际应用的基准测试。
性能测试JS
理想情况下,最好的性能测试是使用您自己的应用程序和您自己的工作负载切换您需要测试的内容:不同的库、机器等。
如果这不可行(通常不可行)。 第一个重要步骤:定义您的工作负载。 它应该反映您的应用程序的工作负载。 在本次演讲中,Vyacheslav Egorov 谈到了您应该避免的糟糕工作负载。
然后,您可以使用 benchmark.js 之类的工具来帮助您收集指标,通常是速度或吞吐量。 在 Sizzle 上,我们有兴趣比较修复或更改如何影响库的系统性能。
如果某些东西的表现非常糟糕,那么下一步就是寻找瓶颈。
如何找到瓶颈? 探查器
我发现执行时间是最好的衡量标准。
您可以在萤火虫中使用console.profile
这是一个用于时间性能的可重用类。 示例包含在代码中:
/*
Help track time lapse - tells you the time difference between each "check()" and since the "start()"
*/
var TimeCapture = function () {
var start = new Date().getTime();
var last = start;
var now = start;
this.start = function () {
start = new Date().getTime();
};
this.check = function (message) {
now = (new Date().getTime());
console.log(message, 'START:', now - start, 'LAST:', now - last);
last = now;
};
};
//Example:
var time = new TimeCapture();
//begin tracking time
time.start();
//...do stuff
time.check('say something here')//look at your console for output
//..do more stuff
time.check('say something else')//look at your console for output
//..do more stuff
time.check('say something else one more time')//look at your console for output
我通常只是测试 javascript 性能,脚本运行多长时间。 jQuery Lover 提供了一个很好的文章链接,用于测试javascript 代码性能,但该文章仅展示了如何测试 javascript 代码运行多长时间。 我还建议阅读名为“在处理大量数据集时改进 jQuery 代码的5 个技巧”的文章。
UX Profiler从用户的角度解决了这个问题。 它对由某些用户操作(点击)引起的所有浏览器事件、网络活动等进行分组,并考虑到延迟、超时等所有方面。
您可以使用https://github.com/anywhichway/benchtest将现有的 Mocha 单元测试与性能测试包装在一起。
黄金法则是在任何情况下都不要锁定您的用户浏览器。 之后,我通常会查看执行时间,然后是内存使用情况(除非你正在做一些疯狂的事情,在这种情况下它可能具有更高的优先级)。
性能测试最近成为一个流行词,但这并不是说性能测试在 QA 中甚至在产品发货之后都不是一个重要的过程。 当我开发应用程序时,我使用了许多不同的工具,其中一些工具如上面提到的chrome Profiler我通常会查看 SaaS 或一些开源的东西,我可以开始并忘记它,直到我收到警报,说有些事情发生了.
有很多很棒的工具可以帮助您密切关注性能,而不必为了设置一些基本警报而跳过箍。 这里有一些我认为值得自己检查的。
为了尝试绘制更清晰的图片, 这里有一个关于如何为 React 应用程序设置监控的小教程。
这是一个非常古老的问题,但我认为我们可以贡献一个基于 es6 的简单解决方案来快速测试您的代码。
这是执行时间的基本工作台。 我们使用performance.now()
来提高准确性:
/** * Figure out how long it takes for a method to execute. * * @param {Function} method to test * @param {number} iterations number of executions. * @param {Array} list of set of args to pass in. * @param {T} context the context to call the method in. * @return {number} the time it took, in milliseconds to execute. */ const bench = (method, list, iterations, context) => { let start = 0 const timer = action => { const time = performance.now() switch (action) { case 'start': start = time return 0 case 'stop': const elapsed = time - start start = 0 return elapsed default: return time - start } }; const result = [] timer('start') list = [...list] for (let i = 0; i < iterations; i++) { for (const args of list) { result.push(method.apply(context, args)) } } const elapsed = timer('stop') console.log(`Called method [${method.name}] Mean: ${elapsed / iterations} Exec. time: ${elapsed}`) return elapsed } const fnc = () => {} const isFunction = (f) => f && f instanceof Function const isFunctionFaster = (f) => f && 'function' === typeof f class A {} function basicFnc(){} async function asyncFnc(){} const arrowFnc = ()=> {} const arrowRFnc = ()=> 1 // Not functions const obj = {} const arr = [] const str = 'function' const bol = true const num = 1 const a = new A() const list = [ [isFunction], [basicFnc], [arrowFnc], [arrowRFnc], [asyncFnc], [Array], [Date], [Object], [Number], [String], [Symbol], [A], [obj], [arr], [str], [bol], [num], [a], [null], [undefined], ] const e1 = bench(isFunction, list, 10000) const e2 = bench(isFunctionFaster, list, 10000) const rate = e2/e1 const percent = Math.abs(1 - rate)*100 console.log(`[isFunctionFaster] is ${(percent).toFixed(2)}% ${rate < 1? 'faster': 'slower'} than [isFunction]`)
这是为特定操作收集性能信息的好方法。
start = new Date().getTime();
for (var n = 0; n < maxCount; n++) {
/* perform the operation to be measured *//
}
elapsed = new Date().getTime() - start;
assert(true,"Measured time: " + elapsed);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.