8

node.js と python のパフォーマンスを比較するための簡単なフィボナッチ テスト プログラムを作成しました。node.js は 200 ミリ秒で終了するのに対し、python は計算を完了するのに 5 秒かかりました。

パイソン

import time

beg = time.clock()
def fib(n):
    if n <=2:
        return 1
    return fib(n-2) + fib(n-1)

var = fib(35)

end = time.clock()
print var
print end - beg

node.js

var beg = new Date().getTime();

function fib(n)
{
    if (n <= 2)
        return 1;

    return fib(n-2) + fib(n-1);
}

var f = fib(35);
var end = new Date().getTime();

console.log(f);
console.log(end - beg);
4

5 に答える 5

13

このような不自然なベンチマークを設定して、速度について包括的な声明を出すのに十分な有用な結果を得ることは、実際には不可能です。ベンチマークは非常に複雑で、場合によっては、ランタイムがベンチマークの一部を完全に除外することさえあります。これは、実行したいことを実行するためのより高速な方法があることに気付いたからです。

ただし、肝心なのは、Python と node.js を比較しているのではなく、それらのインタープリターである CPython と V8 を比較していることです。Python と Javascript には、パフォーマンスに影響を与える同様の言語機能 (ガベージ コレクション、動的型、整数のヒープ割り当てなど) があるため、このベンチマークを実行すると、実際にはインタープリター間の銃撃戦になります。

その文脈では、このようなベンチマークは一般的に価値がありませんが、「この種のことで V8 が CPython よりも速いのはなぜですか」という質問には、ある種の答えがあります。それは JIT コンパイラのせいです

したがって、単純な比較が必要な場合は、JIT を備えた Python インタープリターである PyPy で Python コードを実行してみてください。または、JIT のないランタイムで Javascript コードを実行してみてください。ただし、その時点で、このようなスクリプトを使用してどの言語がより高速であるかを判断するには、ベンチマークが難しすぎて複雑すぎることに気付くでしょう。

于 2013-10-11T02:04:58.943 に答える
9

Node はJIT コンパイラを使用します。これは、同じコード ブロックが同じタイプの入力で何度も実行された場合にそれを認識し、それをマシン コードにコンパイルするように設計されています。Node は、これが純粋な関数であり、結果の一部をインライン展開していることに気付いている可能性もありますが、そのようなコンパイラの性質上、外部からはわかりにくいものです。

CPython は単純なインタープリターであり、指定したとおりに実行します。ただし、 PyPyと呼ばれる Python JIT (Python で書かれたもの) を作成する試みが進行中であり、ご覧のとおり、これまでの結果は有望です。

$ time python2 fib.py
9227465
python2 fib.py  2.90s user 0.01s system 99% cpu 2.907 total
$ time pypy fib.py
9227465
pypy fib.py  1.73s user 0.03s system 96% cpu 1.816 total
于 2013-10-11T02:05:16.710 に答える
5

Python でメモ化されたフィボナッチ関数を使用すると、はるかに高速になることがわかります。

import time

beg = time.clock()

def memoize(f):
    cache = {}
    def decorated_function(*args):
        if args in cache:
            return cache[args]
        else:
            cache[args] = f(*args)
            return cache[args]
    return decorated_function

@memoize
def fib(n):
    if n <=2:
        return 1
    return fib(n-2) + fib(n-1)

var = fib(35)

end = time.clock()
print(var)
print(end - beg)

JavaScript でも同じことができます。

function memoize( fn ) {
    return function () {
        var args = Array.prototype.slice.call(arguments),
            hash = "",
            i = args.length;
        currentArg = null;
        while (i--) {
            currentArg = args[i];
            hash += (currentArg === Object(currentArg)) ?
            JSON.stringify(currentArg) : currentArg;
            fn.memoize || (fn.memoize = {});
        }
        return (hash in fn.memoize) ? fn.memoize[hash] :
        fn.memoize[hash] = fn.apply(this, args);
    };
}

var beg = new Date().getTime();

function fib(n)
{
    if (n <= 2)
        return 1;

    return fib(n-2) + fib(n-1);
}

var f = memoize(fib)(35);
var end = new Date().getTime();

console.log(f);
console.log(end - beg);

JavaScript 側でのパフォーマンスの向上はないように見えます。これは、ここに何らかのメモ化メカニズムが組み込まれていることを示している傾向があります。

クレジット : http://ujihisa.blogspot.fr/2010/11/memoized-recursive-fibonacci-in-python.html , http://addyosmani.com/blog/faster-javascript-memoization/

于 2013-10-11T01:45:26.013 に答える