我发现在 Python 和 Ruby 中,函数调用和循环之类的简单事情,甚至只是增加计数器的循环都比在 Chicken Scheme、Racket 或 SBCL 中花费的时间要多得多。
为什么会这样?我经常听到人们说慢是为动态语言付出的代价,但 Lisps 非常动态,而且速度也不是很慢(它们通常比 C 慢不到 5 倍;Ruby 和 Python 可以达到两位数)。此外,Lisp 风格使用递归,并不总是尾递归,很多,堆栈是堆中延续的链表等,这似乎是应该使 Lisp 比命令式 Python 和 Ruby 慢的东西。
Racket 和 SBCL 是 JITted,但 Chicken Scheme 要么是静态编译的,要么使用非优化的解释器,这两者都应该非常不适合动态语言并且速度很慢。然而,即使使用csi
Chicken Scheme 的简单解释器(它甚至不进行字节码编译!),我的速度也远远超过 Python 和 Ruby。
与类似的动态 Lisp 相比,为什么 Python 和 Ruby 如此慢得离谱?是因为它们是面向对象的并且需要巨大的 vtable 和类型层次结构吗?
示例:阶乘函数。Python:
def factorial(n):
if n == 0:
return 1
else:
return n*factorial(n-1)
for x in xrange(10000000):
i = factorial(10)
球拍:
#lang racket
(define (factorial n)
(cond
[(zero? n) 1]
[else (* n (factorial (sub1 n)))]))
(define q 0)
(for ([i 10000000])
(set! q (factorial 10)))
计时结果:
ithisa@miyasa /scratch> time racket factorial.rkt
racket factorial.rkt 1.00s user 0.03s system 99% cpu 1.032 total
ithisa@miyasa /scratch> time python factorial.py
python factorial.py 13.66s user 0.01s system 100% cpu 13.653 total