【每日一题】- 2020-05-14 - 为什么switch/case 的性能要比使用 mapping(对象)好?
azl397985856 opened this issue · 4 comments
azl397985856 commented
如下代码,是使用了switch case 的redux 的部分代码:
const LOGIN_SUCCESS = "LOGIN_SUCCESS";
const LOGIN_FAILED = "LOGIN_FAILED";
const authState = {
token: "",
error: "",
};
function authReducer(state = authState, action) {
switch (action.type) {
case LOGIN_SUCCESS:
return { ...state, token: action.payload };
case LOGIN_FAILED:
return { ...state, error: action.payload };
default:
return state;
}
}
我们将核心代码改成mapping:
function authReducer(state = authState, action) {
const mapping = {
[LOGIN_SUCCESS]: { ...state, token: action.payload },
[LOGIN_FAILED]: { ...state, error: action.payload }
};
return mapping[action.type] || state;
}
实现效果是一样的, 而且代码更简单明了。 通过benchmark测试,我们发现性能switch好很多,这是为什么?
附benchmark图:
Switch | Mapping |
---|---|
43.033 | 71.609 |
40.247 | 64.800 |
37.814 | 66.123 |
37.967 | 63.871 |
37.616 | 68.133 |
38.534 | 69.483 |
37.261 | 67.353 |
41.662 | 66.113 |
38.867 | 65.872 |
37.602 | 66.873 |
feikerwu commented
贴个benchmark:
node 版本: v10.20.1
机器: 2.6 GHz 六核Intel Core i7 16G
Switch | Object | |
---|---|---|
10 ^ 0 | 0.237ms | 0.083ms |
10 ^ 1 | 0.248ms | 0.108ms |
10 ^ 2 | 0.265ms | 0.259ms |
10 ^ 3 | 0.364ms | 2.264ms |
10 ^ 4 | 1.954ms | 13.573ms |
10 ^ 5 | 5.695ms | 63.255ms |
10 ^ 6 | 26.847ms | 546.769ms |
10 ^ 7 | 163.984ms | 5161.224ms |
10 ^ 8 | 1627.382ms | 50421.401ms |
代码
let count = Math.pow(10, 8)
let swicthCount = count
let objectCount = count
const LOGIN_SUCCESS = "LOGIN_SUCCESS";
const LOGIN_FAILED = "LOGIN_FAILED";
const authState = {
token: "",
error: "",
};
function authReducer(state = authState, action) {
switch (action.type) {
case LOGIN_SUCCESS:
return { ...state, token: action.payload };
case LOGIN_FAILED:
return { ...state, error: action.payload };
default:
return state;
}
}
function authReducerObject(state = authState, action) {
const mapping = {
[LOGIN_SUCCESS]: { ...state, token: action.payload },
[LOGIN_FAILED]: { ...state, error: action.payload }
};
return mapping[action.type] || state;
}
console.time('switch')
while(swicthCount--) {
const action = Math.random() < 0.5 ? LOGIN_SUCCESS : LOGIN_FAILED
authReducer(authState, action)
}
console.timeEnd('switch')
console.time('object')
while(objectCount--) {
const action = Math.random() < 0.5 ? LOGIN_SUCCESS : LOGIN_FAILED
authReducerObject(authState, action)
}
console.timeEnd('object')
wuxiangwa commented
某些浏览器应该对switch做过优化,但是我觉得switch随着case数越来越多,性能肯定会下来,最终应该还是不如mapping,还有一个每次都是创建mapping对象,如果这个对象只初始化一次,也会有所提高
azl397985856 commented
简单来说, if else 会自顶向下计算,时间复杂度最坏的情况是
当然这并不是绝对的, switch 的优化方式可以参考这篇文章:https://www.cnblogs.com/182-7167-2685/p/5374111.html
stale commented
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.