性能:Immutable.js Map vs List vs plain JS
性能:Immutable.js Map vs List vs plain JS
我的基准测试有什么问题吗?为什么Immutable.js的find()方法比array.find()方法慢8倍?
好吧,这样说有些不公平,因为我在Immutable.List中使用了Immutable.Map。但对我来说,这是一个真实世界的例子。如果我使用Immutable.js,那是为了保护不可变性并在某些方面获得性能提升(其中结构共享发挥作用)。仅在对象的根部使用Immutable.js是没有意义的。
下面的基准测试实际上来自于另一个问题(也是我的问题)。我对结果感到非常惊讶,所以我必须单独发布它来弄清楚。我在基准测试中做错了什么,还是性能差异确实这么大?
背景:
我的应用程序中的一些数据可以被视为应用程序元数据。原始数据存储在服务器上的数据库中。对元数据的更新不会经常发生。应用程序将在启动时检查更新后的元数据。
我在应用程序的任何地方都使用Immutable.js,但是对于元数据,我将回退到普通的js。对于这种类型的数据,没有必要使用复杂的结构共享。
测试的目的是在集合中按键查找值:
- 包含10个项的集合
- 查找一百万次
- Mac mini core i7 2.6
结果:
- 使用强制转换键的普通JS对象:8毫秒
- 使用find()的普通JS数组:127毫秒
- 使用数字键的Immutable.Map:185毫秒
- 使用find()的Immutable.List:972毫秒!!让我感到困惑
由于我使用React Native,如果想实现60帧每秒,我总是必须注意16毫秒的限制。基准测试的值似乎不是线性的。只进行100次查找的测试使用Map花费1毫秒,而使用List花费2毫秒。这相当昂贵。
测试代码:
let Immutable = require('immutable');
let mapTest = Immutable.Map()
.set(1, Immutable.Map({value: 'one'}))
.set(2, Immutable.Map({value: 'two'}))
.set(3, Immutable.Map({value: 'three'}))
.set(4, Immutable.Map({value: 'four'}))
.set(5, Immutable.Map({value: 'five'}))
.set(6, Immutable.Map({value: 'six'}))
.set(7, Immutable.Map({value: 'seven'}))
.set(8, Immutable.Map({value: 'eight'}))
.set(9, Immutable.Map({value: 'nine'}))
.set(10, Immutable.Map({value: 'ten'}));
let listTest = Immutable.fromJS([
{key: 1, value: 'one'},
{key: 2, value: 'two'},
{key: 3, value: 'three'},
{key: 4, value: 'four'},
{key: 5, value: 'five'},
{key: 6, value: 'six'},
{key: 7, value: 'seven'},
{key: 8, value: 'eight'},
{key: 9, value: 'nine'},
{key: 10, value: 'ten'}
])
let objTest = {
1: {value: 'one'},
2: {value: 'two'},
3: {value: 'three'},
4: {value: 'four'},
5: {value: 'five'},
6: {value: 'six'},
7: {value: 'seven'},
8: {value: 'eight'},
9: {value: 'nine'},
10: {value: 'ten'}
};
let arrayTest = [
{key: 1, value: 'one'},
{key: 2, value: 'two'},
{key: 3, value: 'three'},
{key: 4, value: 'four'},
{key: 5, value: 'five'},
{key: 6, value: 'six'},
{key: 7, value: 'seven'},
{key: 8, value: 'eight'},
{key: 9, value: 'nine'},
{key: 10, value: 'ten'}
];
const runs = 1e6;
let i;
let key;
let hrStart;
console.log(' ')
console.log('mapTest -----------------------------')
key = 1;
hrstart = process.hrtime();
for(i=0; i let result = mapTest.getIn([key, 'value'] ) key = (key >= 10) ? 1 : key + 1; } hrend = process.hrtime(hrstart); console.info("Execution time (hr): %dms", hrend[0] * 1000 + hrend[1]/1000000); console.log(' ') console.log('listTest -----------------------------') key = 1; hrstart = process.hrtime(); for(i=0; i let result = listTest .find(item => item.get('key') === key) .get('value'); key = (key >= 10) ? 1 : key + 1; } hrend = process.hrtime(hrstart); console.info("Execution time (hr): %dms", hrend[0] * 1000 + hrend[1]/1000000); console.log(' ') console.log('arrayTest -----------------------------') key = 1; hrstart = process.hrtime(); for(i=0; i let result = arrayTest .find(item => item.key === key) .value key = (key >= 10) ? 1 : key + 1; } hrend = process.hrtime(hrstart); console.info("Execution time (hr): %dms", hrend[0] * 1000 + hrend[1]/1000000); console.log(' ') console.log('objTest -----------------------------') key = 1; hrstart = process.hrtime(); for(i=0; i let result = objTest[key].value key = (key >= 10) ? 1 : key + 1; } hrend = process.hrtime(hrstart); console.info("Execution time (hr): %dms", hrend[0] * 1000 + hrend[1]/1000000);