Код Javascript для замедления моего браузера

Я пишу библиотеку для веб-воркеров и хочу проверить разницу между запуском скрипта в потоке главной страницы и в одном или нескольких воркерах. Проблема в том, что я не могу найти короткую функцию, которая достаточно нагрузит мой браузер, чтобы я мог заметить разницу.

Быстрый поиск не дал многого, но, возможно, я просто не знаю, что искать; обычно я стараюсь оптимизировать свой код, а не замедлять его...

Я ищу алгоритмы или шаблоны, которые можно легко реализовать на чистом Javascript, которые не зависят от DOM или XHR и которым можно передать аргумент, чтобы ограничить или указать, как далеко заходит вычисление (без бесконечных алгоритмов); 1 с ‹ среднее время ‹ 10 с.

Дополнительные баллы, если он может быть построен без рекурсии и если он не требует значительного потребления памяти, но при этом максимально интенсивно использует процессор.


person Félix Saparelli    schedule 20.10.2011    source источник
comment
То, что в среднем занимает от 1 до 10 секунд на моем компьютере, может занять ‹1 с на вашем.   -  person NullUserException    schedule 20.10.2011
comment
Во всяком случае, как насчет: v8.googlecode.com/svn/data /benchmarks/v6/run.html   -  person NullUserException    schedule 20.10.2011


Ответы (8)


/**
 * Block CPU for the given amount of seconds
 * @param {Number} [seconds]
 */
function slowdown(seconds = 0.5) {
  const start = (new Date()).getTime()
  let end = start
  while (end - start < seconds * 1000) {
    end = (new Date()).getTime()
  }
}

Вызов этого метода замедлит код на заданное количество секунд (с точностью ~ 200 мс).

person bhovhannes    schedule 27.01.2019

Попробуйте использовать очевидную (и плохую) рекурсивную реализацию для последовательности Фибоначчи:

function fib(x) {
  if (x <= 0) return 0;
  if (x == 1) return 1;
  return fib(x-1) + fib(x-2);
}

Вызов его со значениями от ~ 30 до ~ 35 (в зависимости от вашей системы) должен дать хорошее время «замедления» в диапазоне, который вы ищете. Стек вызовов не должен быть слишком глубоким, а алгоритм должен быть чем-то вроде O(2^n).

person maerics    schedule 20.10.2011
comment
Идеальный. Это немного педантично, но я рекомендую всегда использовать именованные функции при выполнении рекурсии. Использование function fib(x) { ... } гарантирует, что внутри блока функции имя fib будет указывать на эту функцию, тогда как var fib = function(x) { ... } зависит от того, что происходит во внешнем замыкании. - person Jay Adkisson; 20.10.2011
comment
@JayAdkisson: да, это пришло мне в голову вскоре после публикации; спасибо, что оценили мою педантичность =) - person maerics; 20.10.2011
comment
Идеальный. Как я и думал, WebWorkers быстры. fib(30) ~= 5 с в основном, ‹1 с в рабочем. fib(35) разбился main, ~3s в worker. Ух ты! - person Félix Saparelli; 20.10.2011
comment
Почему не var fib = function fib(x){...}? - person ; 16.02.2017
comment
У меня не тормозит даже при значении 30-35...но 40 зависает на странице на несколько секунд. - person ; 16.02.2017

Сгенерируйте массив чисел в обратном порядке и отсортируйте его.

var slowDown = function(n){
  var arr = [];
  for(var i = n; i >= 0; i--){
    arr.push(i);
  }
  arr.sort(function(a,b){
    return a - b;
  });
  return arr;
}

Это можно назвать так:

slowDown(100000);

Или любой номер, который вы хотите использовать.

person Peter Olson    schedule 20.10.2011

Ознакомьтесь с кодом сравнительного анализа, на который ссылается Google V8 Javascript Engine.

person Emmanuel    schedule 20.10.2011
comment
Это интересно, но их никоим образом нельзя легко реализовать или коротко. Которые были в моих требованиях. - person Félix Saparelli; 20.10.2011
comment
Ссылка уже мертва. - person ; 16.02.2017

Почему-то на ум приходит Bogosort. По сути, это алгоритм сортировки, который состоит из:

while not list.isInOrder():
    list.randomize()

Он имеет среднюю сложность O(n * n!) с небольшим объемом памяти, поэтому он должен довольно хорошо замедлять работу.

Основным недостатком является то, что время его работы может составлять от O(n) до O(inf) (хотя на самом деле O(inf) маловероятно).

person Toomai    schedule 20.10.2011
comment
Это также ужасно для тестирования производительности, потому что это очень непредсказуемо. - person Peter Olson; 20.10.2011

Возможно, это то, что вы ищете:

    var threadTest = function(durationMs, outputFkt, outputInterval) {
        var startDateTime = (new Date()).getTime();
            counter = 0,
            testDateTime = null,
            since = 0, 
            lastSince = -1;

        do {
            testDateTime = (new Date()).getTime();
            counter++;

            since = testDateTime - startDateTime;

            if(typeof outputFkt != 'undefined' && lastSince != since && testDateTime % outputInterval == 0) {
                outputFkt(counter, since);
                lastSince = since;
            }
        } while(durationMs > since);

        if(typeof outputFkt != 'undefined') {
                outputFkt(counter, since);
        }

        return counter;
    }

Этот метод будет просто повторять проверку в цикле

durationMS - duartion it should run in miliseconds

OPTIONAL:
outputFkt - a callback method, for logging purpose function(currentCount, milisecondsSinceStart)
outputInterval - intervall the output function will be called

Я подумал, что, поскольку вы не хотите тестировать реальную функцию, и даже NP-сложные задачи имеют соотношение между длиной ввода и временем, это может быть простым способом. Вы можете измерить производительность с любым интервалом и, конечно же, получить количество циклов в качестве возвращаемого значения, поэтому вы можете легко измерить, насколько потоки мешают производительности друг друга, с обратным вызовом даже для каждого цикла.

В качестве примера, вот как я это назвал (здесь используются jQuery и Dom, но, как вы видите, необязательно)

$(document).ready(function() {
    var outputFkt = function(counter, since) {
        $('body').append('<p>'+counter+', since '+since+'</p>');    
    };

    threadTest(1000, outputFkt, 20);

});

Последнее предупреждение: Конечно, эта функция не может быть более точной, чем сам JS. Поскольку современные браузеры могут выполнять гораздо больше, чем один цикл за одну миллисекунду, будет обрезан небольшой хвост.

Обновить

Размышляя об этом... на самом деле использование обратного вызова ouputFkt не только для вывода, но и для более глубокого понимания. Вы можете передать метод, который использует некоторые общие свойства, или вы можете использовать его для проверки большого использования памяти.

person FloydThreepwood    schedule 20.10.2011

Кажется, все решили быть сложными. Почему не это?

function waste_time(amount) {
    for(var i = 0; i < amount; i++);
}

Если вы обеспокоены тем, что браузер полностью оптимизирует цикл, вы можете немного усложнить его:

function waste_time(amount) {
    var tot = 0;
    for(var i = 0; i < amount; i++)
        tot += i;
}
person Nick Johnson    schedule 25.10.2011

Вычислить много квадратных корней вручную?

function sqrt(number, maxDecimal) {
    var cDecimal  = -1;
    var cNumber   = 0;
    var direction = -1;

    while(cNumber * cNumber !== number && cDecimal < maxDecimal) {
        direction = -direction;
        cDecimal++;

        while((cNumber * cNumber - number) / Math.abs(cNumber * cNumber - number) === direction) cNumber += direction * Math.pow(10, -cDecimal);
    }

    return Math.abs(cNumber);
}

function performTest() {
    for(var i = 0; i < 10000; i++) {
        sqrt(i, 3);
    }
}
person Ry-♦    schedule 20.10.2011