yandex-ui / noscript

Noscript: JavaScript MVC Framework for building SPA
http://yandex-ui.github.io/noscript/
MIT License
34 stars 22 forks source link

Производительность ns.ModelCollection #493

Closed chestozo closed 9 years ago

chestozo commented 9 years ago

У нас тут есть коллекция одна, там 460 000+ элементов. И на ней сильно тормозит интерфейс.

Написал пример для исследований:

var count = 100000;

ns.Model.define('col-item', { params: { id: null } });
ns.Model.define('col-test', {
    split: {
        items: '.items',
        model_id: 'col-item',
        params: { id: '.id' }
    }
})

var col = ns.Model.get('col-test', {}).setData({ items: [] });

var models = [];
for (var i = 0; i < count; i++) {
    models.push(ns.Model.get('col-item', { id: i }).setData({}));
}
// t1
col.insert(models);
// t2

Попрафайлил:

count   t1      t2
 50000   557ms   1786ms 
100000  1785ms   5077ms
200000  2699ms  25056ms
300000  3048ms  56058ms 

Тормозит insert, кажется, из-за этого:

for (var i = 0; i < models.length; i++) {
    model = models[i];
    if (model && this.models.indexOf(model) < 0 && insertion.indexOf(model) < 0) {
        insertion.push(model);
    }
}

Перед тем, как вставить модель мы ищём её (инстанс) сразу по 2 массивам.

Варианты оптимизаций, которые я вижу: 1) для this.models хранить какой-то индекс с ключами моделей и искать по ключу (а не по инстансу) 2) для пущей оптимизации можно ввести понятие хэша от ключа и искать по нему. К примеру, model=photo&author-login=ivan&image-id=77 -> ivan:77.

alexeyten commented 9 years ago

Что-то типа такого?

var tmp = {};
this.models.forEach(function(m){tmp[m.key()]=true});
for (var i = 0; i < models.length; i++) {
    model = models[i];
    if (model && !tmp(model.key())) {
        insertion.push(model);
        tmp[model.key()] = true;
    }
}
chestozo commented 9 years ago

Можно и так попробовать, да. Только мне кажется этот объект надо прямо хранить постоянно и синхронизировать с this.models.