Вопрос
Что-то не так с моим бенчмарком? Как может Immutable.js find() быть в 8 раз медленнее, чем array.find()?
Хорошо, не совсем справедливо, так как я использую Immutable.Map внутри Immutable.List. Но для меня это пример реального мира. Если я использую Immutable.js для защиты неизменности и повышения производительности в некоторых аспектах (где происходит совместное использование структуры). Не было бы смысла использовать Immutable.js только в корне объекта.
Ниже приведен пример из другого вопроса (мой тоже). Я был так удивлен результатами, мне пришлось опубликовать его отдельно, чтобы получить его прямо. Я сделал что-то не так в моих тестах, или разница в производительности действительно такая большая?
Фон
Некоторые данные в моем приложении можно рассматривать как метаданные приложения. Исходные данные хранятся в базе данных на сервере. Обновления метаданных не будут выполняться часто. Приложение будет проверять наличие обновленных метаданных при запуске.
Я использую Immutable.js везде, но я вернусь к простым js для метаданных. Нет необходимости в причудливом структурном разделении данных такого типа.
Тест состоит в том, чтобы найти значения по ключу в коллекции
-
Коллекция из 10 предметов
-
Найдите значение миллион раз
-
Mac mini core i7 2.6
Результат:
-
Обычный объект JS с принудительными ключами: 8 мс
-
Обычный массив JS с помощью find(): 127 мс
-
Immutable.Map с числовыми клавишами: 185 мс
-
Immutable.List, используя find(): 972 мс! Я озадачен
Поскольку я использую React Native, мне всегда нужно следить за пределом 16 мс, если я хочу достичь 60 кадров в секунду. Базовые значения не кажутся линейными. Запуск теста с использованием всего 100 поисковых запросов занимает 1 мс с помощью карты и 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<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);