16

我正在为 WebWorkers 编写一个库,我想测试在主页线程中运行脚本与在一个或多个工作人员中运行脚本之间的区别。问题是:我无法找到一个简短的函数,它会使我的浏览器足够紧张,以至于我可以观察到差异。

快速搜索并没有返回太多,但可能只是我真的不知道要搜索什么;通常我会尝试优化我的代码,而不是让它变慢......

我正在寻找可以在纯 Javascript 中轻松实现的算法或模式,它们不依赖于 DOM 或 XHR,并且可以传递一个参数来限制或指定计算的范围(没有无限算法);1 秒 < 平均时间 < 10 秒。

如果它可以在没有递归的情况下构建,并且如果它不会导致显着的内存占用,同时仍然尽可能地占用处理器资源,则可以加分。

4

8 回答 8

11

尝试对斐波那契数列使用明显的(和糟糕的)递归实现:

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).

于 2011-10-20T18:24:52.860 回答
6
/**
 * 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 毫秒)。

于 2019-01-27T20:22:34.593 回答
2

以相反的顺序生成一个数字数组并对其进行排序。

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);

或您想使用的任何号码。

于 2011-10-20T18:27:05.683 回答
2

查看Google V8 Javascript 引擎引用的基准测试代码。

于 2011-10-20T18:33:17.003 回答
1

出于某种原因,我想到了Bogosort。基本上它是一个排序算法,包括:

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

它的平均复杂度O(n * n!)只有很少的内存,所以它应该可以很好地减慢速度。

主要的缺点是它的运行时间可以是从O(n)到 的任何地方O(inf)(尽管实际上O(inf)不太可能)。

于 2011-10-20T18:33:12.543 回答
1

也许这就是你正在寻找的:

    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-Hard 问题在输入长度和时间之间都有一个比率,这可能是一个简单的方法。您可以在任何时间间隔测量性能,当然还可以接收循环数作为返回值,因此您可以轻松地测量线程间干扰彼此性能的程度,甚至在每个循环的基础上都有回调。

作为一个例子,我是这样称呼它的(这里有 jQuery 和 Dom 的用法,但你可以看到可选的)

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

    threadTest(1000, outputFkt, 20);

});

最后一个警告:这个函数当然不能比 JS 本身更精确。由于现代浏览器在一毫秒内可以做不止一个周期,所以会有一个小尾巴被剪掉。

更新

考虑一下......实际上使用ouputFkt回调不仅仅是输出可以提供很好的洞察力。您可以传递一个使用某些共享属性的方法,或者您可以使用它来测试大量内存使用情况。

于 2011-10-20T19:38:23.193 回答
1

每个人似乎都决心变得复杂。为什么不是这个?

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;
}
于 2011-10-25T03:29:49.027 回答
0

手动计算大量平方根?

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);
    }
}
于 2011-10-20T18:36:40.900 回答