JavaScript中try catch语句的性能分析
JavaScript中try catch语句的性能分析
感谢我上一个博客 Array.prototype.forEach 方法详解 提出了两种方法来打破 forEach 循环。
但是网上的博客几乎只提到了第一种方法(try catch + throw 方法),而第二种方法(splice + return 方法)是在了解了forEach方法的原理后才想到的。
所以想比较这两种方法的性能,所以需要比较splice方法和try-catch语句的性能。
//方法一:尝试catch + throw方法
常量 arr = [ 1, 2, 3, 4];
尝试 {
arr。 forEach( ( 项目 ) => {
如果(项目 === 2){
throw new Error( ` value is ${item} Break out forEac loop when `);
}
安慰。日志(项目); // 只打印 1
});
} 抓住 (e) {
安慰。日志(e); //错误:值为2时跳出forEac循环
}
安慰。日志(arr); // [1, 2, 3, 4]
复制代码 //方法二:拼接+返回方法
//迭代时使用splice方法从数组中移除元素
常量 arr = [ 1, 2, 3, 4];
让 spliceArr = null;
arr。 forEach((项目,索引)=> {
如果(项目 === 2){
spliceArr = arr。拼接(索引); // 删除2之后的所有元素并赋值给spliceArr
返回;
}
安慰。日志(项目); // 1
});
arr。 splice(arr.length, spliceArr.length, ...spliceArr); // 缝合删除的元素
安慰。日志(arr); // [1, 2, 3, 4]
复制代码
一、拼接方法的基本介绍及原理
拼接方法可以参考以下两篇博客。
看了下splice方法的源码,发现在splice方法内部调用了一个循环。
所以如果我们简单地用大O符号来分析:
- 方法一:try catch + throw 的性能是O(n)。
- 方法2:拼接+返回的性能是O(n²)。
但是查阅了相关资料后发现try catch语句也是一个非常消耗性能的语句,所以我们需要对try catch语句进行分析。
2.try catch语句的性能分析
try catch 语句可以参考以下三篇博客。
我用的分析方法主要是参考 JS中使用try catch对代码运行的性能影响分析 博客中的方法分为五种方法来讨论。
这篇博客的结果是:当运行环境是Chrome51时,得到的 结果是98.2ms; 1026.9 毫秒; 107.7; 1028.5毫秒; 105.9 毫秒
.
但与我自己实验的结果不同,可能是版本问题,现代浏览器会优化我们的代码。
在我的结果下面
2.1 运行环境:Node.js v16.16.0
测试代码如下:
//空白组1:[不使用try catch对数据取模需要1000万次]
!( 功能 () {
//耗时不try catch
var t = 新日期(); // 启动耗时代码
for ( var i = 0; i < 100000000; i++) {
变量 p = i % 2;
}
安慰。日志(“1:”,新日期() - t); //耗时代码结束
})();
//参考组2:【用try包围耗时代码,内联耗时代码】
!( 功能 () {
// try中内联代码的耗时情况
var t = 新日期(); // 启动耗时代码
尝试 {
for ( var i = 0; i < 100000000; i++) {
变量 p = i % 2;
}
抛出新的错误();
} 捕捉 (e) {}
安慰。日志(“2:”,新日期() - t); //耗时代码结束
})();
//参考组3:【用try包围耗时代码,将耗时代码外化】
!( 功能 () {
// try中内联代码的耗时情况
var t = 新日期(); // 启动耗时代码
函数运行(){
for ( var i = 0; i < 100000000; i++) {
变量 p = i % 2;
}
}
尝试 {
跑();
抛出新的错误();
} 捕捉 (e) {}
安慰。日志(“3:”,新日期() - t); //耗时代码结束
})();
//参考组4:【用catch包围耗时代码,内联耗时代码】
!( 功能 () {
//catch中耗时的内联代码
var t = 新日期(); // 启动耗时代码
尝试 {
抛出新的错误();
} 抓住 (e) {
for ( var i = 0; i < 100000000; i++) {
变量 p = i % 2;
}
}
安慰。日志(“4:”,新日期() - t); //耗时代码结束
})();
//参考第5组:【用catch包围耗时代码,将耗时代码外化】
!( 功能 () {
函数运行(){
for ( var i = 0; i < 100000000; i++) {
变量 p = i % 2;
}
}
//catch中耗时的内联代码
var t = 新日期(); // 启动耗时代码
尝试 {
抛出新的错误();
} 抓住 (e) {
跑();
}
安慰。日志(“5:”,新日期() - t); //耗时代码结束
})();
复制代码
五种方法的结果:都在60-80ms之类的 ,所以它可能是由现代浏览器优化我们的代码引起的。
2.2 运行环境:Chrome版(105.0.5195.127)或Microsoft Edge版(105.0.1343.42)
测试代码如下:
<!DOCTYPE html >
< html lang = "en" >
<头>
<元字符集=“UTF-8”/>
< meta http-equiv = "X-UA-Compatible" 内容 = "IE=edge" />
<元名称=“视口”内容=“宽度=设备宽度,初始比例=1.0” />
< title >1.无 try catch 的情况下 </ title >
</ head >
<身体>
< h1 id = "h1" ></ h1 >
<脚本>
//空白组1:[不使用try catch对数据取模需要1000万次] !( function ( ) { //不使用try catch耗时
常量 h1 = 文档。查询选择器(“#h1”); var t = 新日期 (); // 启动耗时代码
for ( var i = 0 ; i 100000000 ; i++) { var p = i % 2 ; } h1。 innerText = `案例1:消费性能为${ new Date() - t} ms` ; //耗时代码结束 })();</ script >
</ body >
</ html >
复制代码 <!DOCTYPE html >
< html lang = "en" >
<头>
<元字符集=“UTF-8”/>
< meta http-equiv = "X-UA-Compatible" 内容 = "IE=edge" />
<元名称=“视口”内容=“宽度=设备宽度,初始比例=1.0” />
< title >2.将耗时代码用 try 包围,内联耗时代码 </ title >
</ head >
<身体>
< h1 id = "h1" ></ h1 >
<脚本>
//参考组2:[用try包围耗时代码,内联耗时代码] !( function ( ) { // try中内联代码耗时情况
常量 h1 = 文档。查询选择器(“#h1”); var t = 新日期 (); // 启动耗时代码
尝试 { for ( var i = 0 ; i 100000000 ; i++) { var p = i % 2 ; } 抛出新的错误(); } 捕捉 (e) {} h1. innerText = `案例2:消费性能为${ new Date() - t} ms` ; //耗时代码结束 })();</ script >
</ body >
</ html >
复制代码 <!DOCTYPE html >
< html lang = "en" >
<头>
<元字符集=“UTF-8”/>
< meta http-equiv = "X-UA-Compatible" 内容 = "IE=edge" />
<元名称=“视口”内容=“宽度=设备宽度,初始比例=1.0” />
< title >3.将耗时代码用 try 包围,外联耗时代码 </ title >
</ head >
<身体>
< h1 id = "h1" ></ h1 >
<脚本>
//参考组3:[用try包围耗时代码,将耗时代码外化] !( function ( ) { //try中内联函数的耗时情况
常量 h1 = 文档。查询选择器(“#h1”); var t = 新日期 (); // 启动耗时代码
函数运行 ( ) { for ( var i = 0 ; i 100000000 ; i++) { var p = i % 2 ; } } 尝试 { 运行 ();抛出新的错误(); } 捕捉 (e) {} h1. innerText = `案例3:消费性能为${ new Date() - t} ms` ; //耗时代码结束 })();</ script >
</ body >
</ html >
复制代码 <!DOCTYPE html >
< html lang = "en" >
<头>
<元字符集=“UTF-8”/>
< meta http-equiv = "X-UA-Compatible" 内容 = "IE=edge" />
<元名称=“视口”内容=“宽度=设备宽度,初始比例=1.0” />
< title >4.将耗时代码用 catch 包围,内联耗时代码 </ title >
</ head >
<身体>
< h1 id = "h1" ></ h1 >
<脚本>
//参考组4:[用catch包围耗时代码,内联耗时代码] !( function ( ) { //catch中耗时内联代码
常量 h1 = 文档。查询选择器(“#h1”); var t = 新日期 (); // 启动耗时代码
尝试{抛出新错误(); } 捕捉 (e) { for ( var i = 0 ; i 100000000 ; i++) { var p = i % 2 ; } } h1。 innerText = `案例4:消费性能为${ new Date() - t} ms` ; //耗时代码结束 })();</ script >
</ body >
</ html >
复制代码 <!DOCTYPE html >
< html lang = "en" >
<头>
<元字符集=“UTF-8”/>
< meta http-equiv = "X-UA-Compatible" 内容 = "IE=edge" />
<元名称=“视口”内容=“宽度=设备宽度,初始比例=1.0” />
< title >5.将耗时代码用 catch 包围,外联耗时代码 </ title >
</ head >
<身体>
< h1 id = "h1" ></ h1 >
<脚本>
//参考第5组:[用catch包围耗时代码,将耗时代码外化] !( function ( ) { //catch中的耗时内联代码
常量 h1 = 文档。查询选择器(“#h1”); var t = 新日期 (); // 启动耗时代码
函数运行 ( ) { for ( var i = 0 ; i 100000000 ; i++) { var p = i % 2 ; } } 尝试 { 抛出新的错误 (); } 捕捉 (e) { 运行 (); } h1。 innerText = `案例5:消费性能为${ new Date() - t} ms` ; //耗时代码结束 })();</ script >
</ body >
</ html >
复制代码
这五种方法的结果也相似。第一次运行需要100ms以上,但是刷新页面大概需要60-80ms,和node.js环境差不多。
3. 两种跳出forEach循环的方法性能对比
运行代码如下:
//方法一:尝试catch + throw方法
!( 功能 () {
常量 arr = 新数组(100000)。填充(0)。地图((项目,索引)=>索引+ 1);
安慰。时间(“testTime1”); //启动定时器
// 常量开始 = Date.now();
尝试 {
arr。 forEach( ( 项目 ) => {
如果(项目 === 50000){
投掷1;
}
});
} 捕捉 (e) {}
安慰。 timeEnd("testTime1"); //结束时间
// console.log("runtime:", Date.now() - start);
})();
复制代码 //方法二:拼接+返回方法
!( 功能 () {
常量 arr = 新数组(100000)。填充(0)。地图((项目,索引)=>索引+ 1);
安慰。时间(“testTime2”); //启动定时器
// 常量开始 = Date.now();
//当数组元素过多时,会报错RangeError: Maximum call stack size exceeded
让 spliceArr = null;
arr。 forEach((项目,索引)=> {
如果(项目 === 50000){
spliceArr = arr。拼接(索引); // 删除2之后的所有元素并赋值给spliceArr
返回;
}
});
arr。 splice(arr.length, spliceArr.length, ...spliceArr); // 缝合删除的元素
安慰。 timeEnd("testTime2"); //结束时间
// console.log("runtime:", Date.now() - start);
})();
复制代码
结果如下 :
第一种方法比第二种方法好,但是 间隙尺寸 经过 跳出循环条件 受 数组大小 影响,但第一种方法比第二种方法好。
结语
对单词进行编码并不容易。觉得有帮助的朋友会喜欢并关注。
这是迄今为止我所知道的最好的答案,但当然也存在一些误解。
所以如果你对本文有任何疑问,可以在评论区留言。欢迎大家指出文中的错误观点。
版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议。转载请附上原文出处链接和本声明。
这篇文章的链接: https://homecpp.art/2620/9601/1758
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明