Javascript typeof比字面比较快吗?
检查值Javascript typeof比字面比较快吗?,javascript,performance,Javascript,Performance,检查值x是否为布尔值时,为 typeof x==='boolean'比x===true | | x===false快,反之亦然 我原以为文字比较会更快,但比较的类型似乎快了一倍 旁注:我知道这几乎对任何实际目的都不重要 以下是基准代码(免责声明:我不知道如何进行基准测试):视情况而定 为了给出一个绝对的答案,我们必须编译每一段代码/在每一种可能的浏览器/架构组合上观察解释器。然后我们可以给出一个绝对的答案,这个操作需要更少的处理器周期,其他一切都是纯粹的推测。这就是我现在正在做的: 天真的方法
x
是否为布尔值时,为
typeof x==='boolean'
比x===true | | x===false快,反之亦然
我原以为文字比较会更快,但比较的类型似乎快了一倍
旁注:我知道这几乎对任何实际目的都不重要
以下是基准代码(免责声明:我不知道如何进行基准测试):视情况而定
为了给出一个绝对的答案,我们必须编译每一段代码/在每一种可能的浏览器/架构组合上观察解释器。然后我们可以给出一个绝对的答案,这个操作需要更少的处理器周期,其他一切都是纯粹的推测。这就是我现在正在做的:
天真的方法
让我们假设引擎不执行任何优化。他们只是执行规范中定义的每个步骤。然后,对于每个测试用例,都会发生以下情况:
typeof x==='boolean'
(1) 将查找x
的类型。由于引擎可能将一个通用的“JavaScript值”表示为一个结构,该结构具有指向实际数据的指针和值类型的枚举,因此获取描述该类型的字符串可能是在类型->类型字符串映射中进行查找
(2) 现在我们有两个字符串值,需要比较('boolean'=='boolean'
)。首先,必须检查类型是否相等。这可能是通过比较两个值的类型字段和一个位相等(意思是:一个处理器op)来实现的
(3) 最后,必须比较该值是否相等。对于字符串,这意味着对两个字符串进行迭代,并相互比较字符
x==true | | x==false
(1) 首先,必须如上所述比较x
和true
和x
adfalse
的类型
(2) 其次,必须对值进行比较,布尔值是按位质量的(意思是:一个处理器操作)
(3) 最后一步是or表达式。给定两个值,首先必须检查它们的真实性(这对于布尔型非常容易,但我们仍然必须再次检查它们是否真的是布尔型),然后才能执行or操作(按位or,意思是:一个处理器op)
那么哪一个更快呢?如果我不得不猜测的话,第二种方法,就像第一种方法一样,必须实现字符串相等,这可能需要更多的迭代
最优方法
一个非常聪明的编译器可能会意识到,只有当x的类型是布尔类型时,typeof x===='boolean'
才是真的。因此可以将其优化为(C++伪代码):
这只是几个处理器操作,所以速度非常快。与naive方法相比,我们保存了一个字符串比较和多个类型检查。发动机会进行这样的优化吗?可能是因为typeof
检查非常常见,并且非常容易优化(因此这是一个轻松的胜利)
我们可以优化x==true | | x==false
?是的,正如我们所知,true
和false
的类型可以归结为(C++伪代码):
不能进一步优化吗?编译器不能看到x->value
和吗!x->value
是互斥的,因此它实际上与上面的代码完全相同。编译器会进行这种优化吗?我不知道。这显然不是那么容易,而且优化x | |!x实际上是开发人员可以进行的简单优化
因此,在一个完美的世界中,有了一个非常周到的编译器,第一个会更快
但是编译器会优化那么多吗?视情况而定。如今,引擎首先采用简单的方法(因为编译也会花费时间),并且只有在函数变热(经常调用)时才会进行优化。这就是测试用例中的情况(这就是为什么第二个更快)。真实世界的代码是否会变得热门取决于用例
外卖
在我的设备上,第一个版本执行451701256操作/秒(!!)。假设处理器以1.5 GHz的频率运行,那么每次操作大约需要3个处理器周期。那么快吗?对!
第二个版本的执行速度为198308952 ops/s。这大约是每个操作7个处理器周期。是不是慢了一倍?对太慢了!不可能还有其他代码段会消耗更多的处理器周期
进一步思考
一个非常常见的优化是在推导参数的数据类型后向下编译函数。这意味着如果你这样做了
const check = it => typeof it === "boolean";
for(let i = 0; i < 100000; i++) check(true); // make function hot
const check=it=>typeof=it==“boolean”;
对于(设i=0;i<100000;i++)检查(true);//使函数变热
该函数可能被编译为
boolean check(/*deduced datatype*/ boolean it) {
return true; // <- even faster than anything above
}
boolean检查(/*推断数据类型*/boolean it){
return true;//你能分享一下你用来做基准测试的代码吗?我可以用是和否来回答你的问题。只是为了好玩,我基准测试了x==!!x
,速度几乎和typeof
一样快。但到目前为止,赢家是x==Boolean(x)
。我猜一个人可以通过跳过已经是布尔运算之类的运算来进行优化。@Jonaswillms添加到post@JohnMontgomery我找不到任何方法之间的明显区别。
const check = it => typeof it === "boolean";
for(let i = 0; i < 100000; i++) check(true); // make function hot
boolean check(/*deduced datatype*/ boolean it) {
return true; // <- even faster than anything above
}