У меня возникли проблемы с пониманием того, почему время будет отличаться для следующих двух реализаций console.time. Я пытаюсь протестировать написанную мной функцию, но когда я реализую console.time двумя следующими способами, я получаю очень разные ответы ...
Чтобы попытаться диагностировать это, я использовал Array.prototype.sort(), и были получены такие же несоответствия по времени. arr - это массив длины n со случайными целыми числами. Я тестировал его с массивами случайных целых чисел длиной 10, 100, 1000, 10000, 100000.
Примечание: Я знаю, что API представление существует, но я хочу понять, что происходит с console.time.
Способ 1
function timeLog(title, arr) {
console.time(title);
arr.sort();
console.timeEnd(title);
}
timeLog('time test 1', arr);
Способ 2:
console.time('time test 2');
arr.sort();
console.timeEnd('time test 2');
Мои результаты:
with method 1
10 item array: 0.198ms
100 item array: 0.196ms
1000 item array: 3.386ms
10000 item array: 65.558ms
100000 item array: 326.774ms
with method 2
10 item array: 0.022ms
100 item array: 0.081ms
1000 item array: 0.534ms
10000 item array: 12.865ms
100000 item array: 77.395ms
Запускаемый фрагмент:
function randomArray(n) {
return Array.apply(null, Array(n))
.map(function() {
return Math.floor(Math.random() * 1000);
});
}
function timeLog(title, array) {
console.time(title);
array.sort();
console.timeEnd(title);
}
var arr10 = randomArray(10);
var arr100 = randomArray(100);
var arr1000 = randomArray(1000);
var arr10000 = randomArray(10000);
var arr100000 = randomArray(100000);
var arr10_2 = arr10.slice();
var arr100_2 = arr100.slice();
var arr1000_2 = arr1000.slice();
var arr10000_2 = arr10000.slice();
var arr100000_2 = arr100000.slice();
console.info('method 1: with timeLog function')
timeLog('10 item array', arr10)
timeLog('100 item array', arr100)
timeLog('1000 item array', arr1000)
timeLog('10000 item array', arr10000)
timeLog('100000 item array', arr100000)
console.info();
console.info('method 2: just console.time');
console.time('10 item array-2')
arr10_2.sort()
console.timeEnd('10 item array-2')
console.time('100 item array-2')
arr100_2.sort()
console.timeEnd('100 item array-2')
console.time('1000 item array-2')
arr1000_2.sort()
console.timeEnd('1000 item array-2')
console.time('10000 item array-2')
arr10000_2.sort()
console.timeEnd('10000 item array-2')
console.time('100000 item array-2')
arr100000_2.sort()
console.timeEnd('100000 item array-2')Обновите свой вопрос, добавив минимальный воспроизводимый пример, демонстрирующий проблему, в идеале работоспособный, используя Stack Snippets (кнопка панели инструментов [<>]; вот как это сделать).
Хороший улов! Да, я убедился, что они не работают с одним и тем же массивом, прежде чем запускать эти тесты. Однако они не работают с массивами с одинаковыми элементами, поэтому мне придется это изменить.



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Думаю, просто вы тестируете их обоих одновременно, и оптимизация начинается уже на первом проходе. (И / или другие проблемы с методологией тестирования, такие как повторная сортировка одного и того же массива и т.д .; не могу сказать, о чем идет речь.)
Если я сделаю это с массивом из 10 000 элементов, стараясь использовать значения одно и тоже для каждого теста (и следя за тем, чтобы второй не сортировал массив, отсортированный по первому), в Chrome я надежно вижу более быстрое время для второй sort, чем первый - независимо от того, использую ли я сначала timeLog или сначала встроенный код:
Сначала используйте timeLog:
var arr1 = Array.from({length:10000}, () => Math.floor(Math.random() * 1000));
var arr2 = arr1.slice();
function timeLog(title, arr) {
console.time(title);
arr.sort();
console.timeEnd(title);
}
timeLog('time test 1', arr1);
console.time('time test 2');
arr2.sort();
console.timeEnd('time test 2');Сначала используйте встроенный код:
var arr1 = Array.from({length:10000}, () => Math.floor(Math.random() * 1000));
var arr2 = arr1.slice();
function timeLog(title, arr) {
console.time(title);
arr.sort();
console.timeEnd(title);
}
console.time('time test 2');
arr2.sort();
console.timeEnd('time test 2');
timeLog('time test 1', arr1);А если я сделаю это дважды, я вижу, что разница исчезает во второй раз:
Дважды, используя сначала timeLog:
var arr1 = Array.from({length:10000}, () => Math.floor(Math.random() * 1000));
var arr2 = arr1.slice();
var arr3 = arr1.slice();
var arr4 = arr1.slice();
function timeLog(title, arr) {
console.time(title);
arr.sort();
console.timeEnd(title);
}
timeLog('timeLog 1', arr1);
console.time('inline 1');
arr2.sort();
console.timeEnd('inline 1');
timeLog('timeLog 2', arr1);
console.time('inline 2');
arr2.sort();
console.timeEnd('inline 2');Дважды, используя сначала встроенный код:
var arr1 = Array.from({length:10000}, () => Math.floor(Math.random() * 1000));
var arr2 = arr1.slice();
var arr3 = arr1.slice();
var arr4 = arr1.slice();
function timeLog(title, arr) {
console.time(title);
arr.sort();
console.timeEnd(title);
}
console.time('inline 1');
arr2.sort();
console.timeEnd('inline 1');
timeLog('timeLog 1', arr1);
console.time('inline 2');
arr2.sort();
console.timeEnd('inline 2');
timeLog('timeLog 2', arr1);Интересно. Да, я не использовал одни и те же значения каждый раз, поэтому мне придется попробовать. Настолько интересно, что порядок не имеет значения! Спасибо за помощь!
@SneakyToes: Ну, порядок вещей имеет смысл. V8 запускает интерпретируемый код (раньше он использовал быстрый компилятор, но теперь он начинается с интерпретатора), а затем компилирует код на лету, если он выглядит как горячая точка. Array#sort реализован в JavaScript (код здесь), поэтому вы сортируете массив из 10 000 записей, и он скажет, что функция сравнения является точкой доступа и компилируется ... :-)
Гм ... вы вызываете
timeLogс тремя аргументами, но у него только два формальных параметра, а второй -arr, но вы передаетеmyFunction...? Я предполагаю ошибку теста. Отдельно: тестируете ли вы их на одних и тех же исходных данных? Надеюсь, вы не тестируете второй в массиве, отсортированном первым ...