Почему отличается время перебора объектов одного класса от множества классов?
Из-за ошибки возникла ситуация, которую очень хотелось бы понять. Время на цикл (50 тыс итераций) перебора и обращение к свойствам экземпляров одного класса существенно отличается от времени перебора экземпляров разных классов. 2 мс против 40мс.
Возможно у кого нибудь будут мысли о причинах такого поведения.
Код:
let length = 50000;
let list_of_one = [];
let main_class = getClass();
for(let i = 0; i<length;i++){
list_of_one.push(new main_class())
}
let list_of_many = [];
for(let i = 0; i<length;i++){
let main_class = getClass()
list_of_many.push(new main_class())
}
performanceTest(list_of_one) // результат ~2ms
performanceTest(list_of_many) // результат ~40ms
function performanceTest(list){
console.time('time')
let c = list.length
for(let i = 0; i<c;i++){
list[i].buffer_data_calc.color[3] = i
}
console.timeEnd('time')
}
function getClass(){
class Main {
id=23;
type= 1;
buffer_data_calc={color:[1,2,3,4,5]};
init(){
}
}
return Main
}
p.s было замечено что уже на поиск свойства buffer_data_calc уходит большая времени...
Ответы (2 шт):
Почему вы считаете что в цикле у вас одинаковые операции. Дело в том что в первом случае вы подготовили класс и в цикле добавляете новые экземпляры этого класса. Но во втором случае вы генерирует новый класс в цикле дополнительно, что не может не занимать время и только потом создаёте новый экземпляр класса. Проверьте на примере явно созданный 5-10 классов и добавьте их в цикле. Я не думаю что в этом будет существенная разница.
На счёт теста. У вас не однородный и однородный массивы. Понятно чтоб получить свойство в однородном будет быстрее нежели постоянно узнавать в различном.
Есть 2 момента.
Когда функция работает с объектами одного и того же типа, она компилируется под этот тип. Количество одновременно существующих скомпилированных функций ограничено. Если тип оказывается разным, браузеру может понадобиться откуда-то что-то достать (скомпилировать функцию, достать альтернативный скомпилированный вариант или что-то ещё) и на это потребуется время. Вот, Илья Климов рассказывает как добавление части объектов одного поля сказалось на производительности.
И второй момент, касающийся именно приведённого примера. При доступе к свойствам есть обычный доступ, а есть доступ при котором уже известно, в каким сдвигом оно записано. Браузер старается в большинстве случаев использовать второй, поскольку он быстрее. Но в твоём массиве вообще все объекты разных классов - скорее всего при таком массиве браузер откажется от второго варианта и будет использовать первый. Если сократить число классов до 2 (или нескольких), то ситуация может измениться.
PS: Ответ полностью основан на моих предположениях и знаниях. Я не пытался компилировать и исследовать приведённый код, чтобы дать более детальный и/или точный ответ по нему.
PPS: Видео 2015 года, что-то могло уже и измениться. Но на конвертацию объектов из быстрого вида в словари я натыкался в прошлом году (пришлось фиксить - на словари просто памяти не хватало и страница валилась). Впрочем, именно словари к вопросу не относятся, поскольку в цикле нет модификации свойств.