16

私は WebWorkers 用のライブラリを作成しています。メイン ページ スレッドでスクリプトを実行する場合と、1 つまたは複数のワーカーでスクリプトを実行する場合の違いをテストしたいと考えています。問題は、違いを観察できるほどブラウザに負担をかける短い関数をすぐに見つけることができないことです。

クイック検索ではあまり結果が得られませんでしたが、何を検索すればよいかよくわからないだけかもしれません。通常、コードを遅くするのではなく、コードを最適化しようとします...

純粋な 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 に答える
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 Engine が参照するベンチマーク コードを確認してください。

于 2011-10-20T18:33:17.003 に答える
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 に答える
1

なぜかボゴソートが思い浮かびます。基本的には、次のもので構成される並べ替えアルゴリズムです。

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 Problems でさえ入力の長さと時間の比率があるので、これは簡単な方法であると考えました。任意の間隔でパフォーマンスを測定でき、もちろんループ回数を戻り値として受け取ることができるため、サイクル単位でもコールバックを使用して、スレッドが互いにパフォーマンスをどの程度干渉するかを簡単に測定できます。

例として、ここに私がそれをどのように呼んだかを示します(jQueryとDomの使用法はここにありますが、ご覧のとおりオプションです)

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

    threadTest(1000, outputFkt, 20);

});

最後の警告:もちろん、この関数は JS 自体よりも正確ではありません。最新のブラウザは 1 ミリ秒で 1 サイクルよりもはるかに多くの処理を実行できるため、少し切り詰められる部分があります。

アップデート

考えてみてください...実際にouputFktコールバックを出力以外にも使用すると、優れた洞察が得られる可能性があります。いくつかの共有プロパティを使用するメソッドを渡すか、それを使用して大量のメモリ使用量をテストできます。

于 2011-10-20T19:38:23.193 に答える
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 に答える