Immutable.js使用数字键映射(包括性能测试)

Mic*_*ael 6 javascript immutable.js

我在React Native应用程序中使用Redutable使用Immutable.js.

元数据(例如查找表)从服务器获取,并作为Immutable.Map在应用程序中本地保存.查找值的键是整数(db中的主键).

当我获取数据时,所有整数键都被强制转换为字符串.这是js对象的正常行为.因此,当创建查找映射时,键将是字符串.

例:

let colors = Immutable.Map({
  '10': 'yellow',
  '20': 'pink',
  ..
})
Run Code Online (Sandbox Code Playgroud)

引用查找值的对象将引用存储为数字,如下所示:

let michael = Immutable.Map({
  name: 'Michael',
  colorId: 10
})
Run Code Online (Sandbox Code Playgroud)

由于Immutable.js不会将数字键强制转换为字符串,因此无法执行此操作:

let color = colors.get(michael.get('colorId'))
Run Code Online (Sandbox Code Playgroud)

以上内容与:

let color = colors.get(10)
Run Code Online (Sandbox Code Playgroud)

这不起作用,因为id是一个字符串.这可行:

let color = colors.get('10')
Run Code Online (Sandbox Code Playgroud)

我通常使用Immutable.List来存储从服务器获取的数据集.要获得一个项目,我使用find().但是经常访问小的查找表(基本上是应用程序元数据)并且需要快速.

你是如何解决这个问题的?以下是一些需要考虑的选择:

1.搜索时手动将键转换为字符串

let color = colors.get(michael.get('colorId') + '') 
Run Code Online (Sandbox Code Playgroud)

缺点:

  • 不是一个有吸引力的解 似乎错误修剪给我.

2.将普通js对象用于查找列表

优点:

  • 对象键查找在js中很快
  • 自动强制键到字符串,两种方式(写和读)

缺点:

  • 理想情况下,我想在任何地方使用Immutable.js.

3.将List.find()用于查找表

优点:

  • 与大数据集的概念相同

缺点:

  • 我不知道使用List.find()而不是Map.get()对性能的影响

4.仔细制作Immutable.Map以使用数字键

let colors = new Immutable.Map()
  .set(10, 'yellow')
  .set(20, 'pink')
Run Code Online (Sandbox Code Playgroud)

优点:

  • 地图中的键将匹配引用键的值(即两者都是数字)

缺点:

  • 笨重
  • 键已经被强制转换为通过线路发送的json对象中的字符串,所以我基本上将它们转换回数字(我认为)

编辑..做了一些性能测试

来自简单性能测试的有趣数据.

  • 查找列表中的10个项目
  • 找到一百万次的价值
  • Mac mini核心i7 2.6

Immutable.Map与数字键:185毫秒

使用find()的Immutable.List:972 ms

带有强制密钥的普通JS对象:8毫秒

使用find()的普通JS数组:127毫秒

因为我正在使用React Native,如果我想达到60 fps,我总是要注意16 ms的限制.基准值似乎不是线性的.仅使用100次查找运行测试需要1 ms的Map和2 ms的List.那太贵了.

我在基准测试中做错了吗?否则我想我现在必须离开Immutable.js :(

测试代码

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<runs; 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<runs; 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<runs; 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<runs; 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);
Run Code Online (Sandbox Code Playgroud)