我的字符串距离功能运行得太慢了。我将其缩小到以下(时间是10K字符串比较):
// desired behavior - 400ms
dp[c + 257] = Math.min(dp[c + 256] + 1, dp[c + 1] + 1, dp[c] + (a[i] != b[j]));
// this is somewhat faster - 300ms
dp[c + 257] = Math.min(dp[c + 256] + 1, dp[c + 1] + 1);
dp[c + 257] = Math.min(dp[c + 257], dp[c] + (a[i] != b[j]));
// even faster - 50ms
dp[c + 257] = Math.min(dp[c + 256] + 1, dp[c + 1] + 1);
dp[c + 257] = Math.min(dp[c + 257], dp[c] + (a[i] != b[j] ? 1 : 0));
首先,将Math.min
分成两个调用比使用3个参数一次更快 - 这怎么可能?其次,为什么添加一个显式的三级表达式比依赖从bool到int的隐式转换要快得多?
这是一个小提琴:https://jsfiddle.net/6bnLvbt6/
答案 0 :(得分:2)
您有3个测试用例:
Math.min
,类型为cast(bool为int)Math.min
使用 2 参数进行调用,其中第二个调用具有类型转换Math.min
使用 2 参数调用,每个参数都没有类型强制转换在1和2& 3之间还存在另一个区别,其中一些参数存在额外的+ 1
。我认为这是一个错误。
隐式类型转换似乎是最昂贵的。如果从1
中删除隐式类型转换,则会得到:
dp[c + 257] = Math.min(dp[c + 1], dp[c + 256], dp[c] + (a[i] != b[j] ? 1 : 0));
这需要250ms
(vs 60ms
为3)。这仍然表明带有3个参数的Math.min
更慢。让我们进行更多调查。
如果您将测试用例简化为:
// 1
for(var i = 0; i < 10000; i += 1) {
Math.min(1, 2, 3);
}
// 2
for(var i = 0; i < 10000; i += 1) {
Math.min(1, 2);
Math.min(1, 3);
}
我的计算机上的结果是:1
需要2500ms
,2
需要87ms
。如果你向Math.min
添加更多参数,你会发现每增加一个参数,它会在500ms
之间整齐地增加,这可以揭示实现的内容。
浏览器供应商优化经常使用的功能。如果具有2个以上参数的Math.min
不常见,则这些结果并不奇怪。你在这里看到的是Math.min
有两个实现:一个用于两个参数,这是非常优化的,另一个用于更多参数,这些参数未经优化。对于v8,这由apsillers确认:v8 source on github