Производительность Javascript: console.time

У меня возникли проблемы с пониманием того, почему время будет отличаться для следующих двух реализаций 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')

Гм ... вы вызываете timeLog с тремя аргументами, но у него только два формальных параметра, а второй - arr, но вы передаете myFunction ...? Я предполагаю ошибку теста. Отдельно: тестируете ли вы их на одних и тех же исходных данных? Надеюсь, вы не тестируете второй в массиве, отсортированном первым ...

T.J. Crowder 20.03.2018 19:14

Обновите свой вопрос, добавив минимальный воспроизводимый пример, демонстрирующий проблему, в идеале работоспособный, используя Stack Snippets (кнопка панели инструментов [<>]; вот как это сделать).

T.J. Crowder 20.03.2018 19:15

Хороший улов! Да, я убедился, что они не работают с одним и тем же массивом, прежде чем запускать эти тесты. Однако они не работают с массивами с одинаковыми элементами, поэтому мне придется это изменить.

Sneaky Toes 20.03.2018 19:36
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
1
3
144
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Думаю, просто вы тестируете их обоих одновременно, и оптимизация начинается уже на первом проходе. (И / или другие проблемы с методологией тестирования, такие как повторная сортировка одного и того же массива и т.д .; не могу сказать, о чем идет речь.)

Если я сделаю это с массивом из 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);

Интересно. Да, я не использовал одни и те же значения каждый раз, поэтому мне придется попробовать. Настолько интересно, что порядок не имеет значения! Спасибо за помощь!

Sneaky Toes 20.03.2018 19:32

@SneakyToes: Ну, порядок вещей имеет смысл. V8 запускает интерпретируемый код (раньше он использовал быстрый компилятор, но теперь он начинается с интерпретатора), а затем компилирует код на лету, если он выглядит как горячая точка. Array#sort реализован в JavaScript (код здесь), поэтому вы сортируете массив из 10 000 записей, и он скажет, что функция сравнения является точкой доступа и компилируется ... :-)

T.J. Crowder 20.03.2018 19:55

Другие вопросы по теме