为什么python在递归上比node.js慢得多

为什么python在递归上比node.js慢得多,python,node.js,Python,Node.js,我编写了一个简单的fibonacci测试程序来比较node.js和python的性能。 结果表明,python花了5秒完成计算,而node.js只花了200毫秒 为什么python在这种情况下表现如此糟糕 蟒蛇 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()

我编写了一个简单的fibonacci测试程序来比较node.js和python的性能。 结果表明,python花了5秒完成计算,而node.js只花了200毫秒 为什么python在这种情况下表现如此糟糕

蟒蛇

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
导入时间
beg=time.clock()
def纤维(n):

如果在Python中使用记忆fibonacci函数,您将看到它变得更快:

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)
导入时间
beg=time.clock()
def记忆(f):
缓存={}
def/U函数(*args):
如果参数在缓存中:
返回缓存[args]
其他:
缓存[args]=f(*args)
返回缓存[args]
返回函数
@回忆
def纤维(n):

如果n真的不可能建立这样一个人为的基准,并得到足够有用的结果来对速度做出全面的陈述;基准测试非常复杂,在某些情况下,运行时甚至可以完全排除基准测试的一部分,因为他们意识到有一种更快的方法来完成你告诉它你想做的事情

然而,底线是,您不是在比较Python和node.js,而是在比较它们的解释器:CPython和V8。Python和Javascript具有影响性能的类似语言特性(垃圾收集、动态类型,甚至我认为整数的堆分配?),因此当您运行这个基准测试时,解释器之间真的会发生冲突

在这种情况下,即使这样的基准测试通常没有价值,“为什么V8在这方面比CPython快”这个问题确实有一个答案:这是因为JIT编译器的缘故

因此,如果您想要一个直接的比较,请尝试在PyPy上运行Python代码,PyPy是一个带有JIT的Python解释器。或者尝试在没有JIT的运行时上运行Javascript代码。然而,此时,您可能会发现基准测试太难、太复杂,无法使用这样的脚本来判断哪种语言更快。

节点使用一个节点,该节点用于注意同一代码块在相同类型的输入下多次运行并将其编译为机器代码。Node甚至可能注意到这是一个纯函数,并且内联了一些结果,但是从这种编译器的本质来看,很难从外部进行区分

CPython是一个天真的口译员,会完全按照你说的去做。然而,有人正在尝试编写一个名为的Python JIT(用Python编写),正如您所看到的,thusfar的结果很有希望:

$ 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

我本想写这篇文章作为评论,但由于我还没有足够的观点,我补充了另一个答案

正如许多答案/评论所提到的,现在比原始问题的日期晚了几年,我想我应该更新一下最新版本的python代码,并从问题中运行python代码:

Windows 7 64位,英特尔至强E5-1607 3GHz。

U:>python——版本
Python 2.7.5

U:>python fib.py
9227465
3.54921930198

U:>pypy——版本
Python 2.7.3(2cec7296d7fb,2013年11月12日,13:24:40)
[PyPy 2.2.0,带MSC v.1500 32位]

U:>pypy纤维py
9227465
0.385597246386

因此,在这个时间点上,比这个微观基准快了9倍以上。看起来node.js仍然会更快


干杯,Tim。

有一种方法可以通过使用lru_cache()decorator来加速Cpython的递归。然后,结果将比NodeJS来得更快。在下面的链接中找到有关递归和lru_cache()的更多信息

从functools导入lru\U缓存
导入时间
beg=时间。时间()
@lru_缓存()
def纤维(n):
如果n python.py
9227465
0

这是一个测试程序,不是出于实际目的,我故意这样写的。在Memonization下运行这两个测试可以提供一些关于发生了什么的线索。问题是关于递归函数在两个环境(Paython,Node.js)中的性能,但您的答案是优化算法。提示是javascript可能使用JIT,这就是@eevee confirmedYou正在比较的实现:CPython和Node.js。语言比较可以是Python(实现包括CPython、PyPy、IronPython和Jython)和JavaScript(实现包括SpiderMonkey、V8和Chakra)。这个问题给出了一些非常有启发性的答案。谢谢大家。
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);
$ 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
from functools import lru_cache
import time
beg = time.time()

@lru_cache()
def fib(n):     
    if n <=2:        
        return 1 
    return fib(n-2) + fib(n-1)  
var = fib(35)  
end = time.time() 
print (var)
print (end - beg)

C:\Users\steps\Desktop>python dot.py 
9227465
0.0