1
Paranoid 2014-05-23 10:17:02 +08:00
真巧, 刚刚看书刚好看到 斐波那契 这块, LZ 算法还可以被优化. 利用自底向上的动态规划来保存需要前置的值在进行计算. 时间从指数级变成线性.
|
3
qloog 2014-05-23 10:23:16 +08:00
看来V8还是挺厉害的,比想象的厉害~ python居然差这么多。。。
|
4
song940 2014-05-23 10:27:57 +08:00
Python 不是会生成 *.pyc 文件么 , 这对 Python 执行速度没有帮助 ?
|
5
mengzhuo 2014-05-23 10:30:50 +08:00 1
Python用generator试试?
https://gist.github.com/mengzhuo/01fb4460dfec4fb1cb56 |
6
mengzhuo 2014-05-23 10:33:21 +08:00
Python递归还是少用为妙,太多就max deep了,换成stackless或者pypy可以性能翻3倍
|
7
duzhe0 2014-05-23 10:35:14 +08:00 1
以前miloyip做过一个渲染测试,javascript(V8)是脚本语言里最快的
http://www.cnblogs.com/miloyip/archive/2010/07/07/languages_brawl_GI.html |
8
zoowii 2014-05-23 10:36:34 +08:00
v8里自带了缓存?
你用每次计算都是不同的值来比较下呢,比如每次加大随机数循环 |
9
fwee 2014-05-23 10:41:09 +08:00
|
10
xdeng 2014-05-23 10:41:46 +08:00
后面的那个脚本会被优化掉的
|
11
skybr 2014-05-23 10:42:24 +08:00 3
js的数值运算不带gmp支持, python的带, 这个测试一开始就不公平.
跑这种应该用pypy的, 目前看, 只要预热足够, pypy的性能是高于node的. @song940 主要提升加载速度, pyo可以去掉assert |
12
zog 2014-05-23 10:48:24 +08:00
这样试一试
def fun(num): aList = [] for i in range(num): aList.append((i+1) if i < 2 else sum(aList[-2:])) return aList print(fun(10)) |
13
yueyoum 2014-05-23 10:51:04 +08:00
|
14
yueyoum 2014-05-23 10:51:26 +08:00
|
15
yueyoum 2014-05-23 10:55:06 +08:00
LZ 你的JS代码 我执行的结果为:
wang[10:53][/tmp]$ time node x.js 165580141 real 0m2.235s user 0m2.224s sys 0m0.028s 比 python 慢多了。 JS不熟悉,就不说了。 但对于python,说两点: 1, 别用递归, 你把 40 调大一点试试, 不是速度慢的问题,是直接 栈溢出, 程序崩溃的问题。 2, 你的代码有误,结果不对 |
16
chevalier 2014-05-23 10:57:26 +08:00
我想说一句,这三种语言的应用场景都是IO密集型的,单纯比较计算速度有意义吗?
|
17
riaqn 2014-05-23 11:03:07 +08:00 1
感觉是刘翔和姚明比赛跑400米,然后刘翔赢了……
|
18
codingpp OP @yueyoum
1 这个是测试,是来对比的,我是专门写了递归的程序,下面有不是递归的程序测试,两种测试都表明python是慢的。程序也都运行出结果了,没有栈溢出的情况 2 代码哪里有误?程序运行完成后我都打印出来了结果,结果都是正确的 你的执行python运行了多长时间? |
19
binux 2014-05-23 11:09:31 +08:00
月经,你要测就测你直接的实际应用
函数调用,循环,变量,运算都差异太大你这混着测算什么东西? |
21
codingpp OP @binux
如果测试实际应用,写一个web程序,那本文的标题计算性能就该改成io性能了 5000万次web查询与5000万次计算语言性能上应该已经无足轻重了 我这里就是想要测试一下计算性能,做了最简单的循环计算,你说的差异太大不可以这样测是什么意思,应该去测什么? |
22
ddyy 2014-05-23 11:29:47 +08:00
所有脱离实际项目的性能测试都是耍流氓
|
23
yueyoum 2014-05-23 11:30:01 +08:00
@codingpp
1. 你把40搞大一点 2. 按照 斐波那契数列 数列的定义, F(0) = 0 F(1) = 1 F(2) = F (1) + F (0) = 1 你看看的程序输出的是1 吗? 你看我的gist吧, 0.017s |
24
jiang42 2014-05-23 11:34:19 +08:00 1
LZ 你这不科学
1. 测试次数太少,使用的平台太少 2. 测试用的程序不行,没有测试到方方面面 3. 我若是没记错的话,nodejs 用了 JIT 来优化的 我用 pypy 试了试,差距在 3.5 倍左右 如果用 numpy 会更快的吧- - 4. 一个程序高效与否,还是得看写程序的人的算法功底,如果 Jeff Dean 写出来的代码都不行,那 才考虑换语言。 |
25
Feiox 2014-05-23 11:36:49 +08:00
|
26
jsonline 2014-05-23 11:39:20 +08:00
知道 JS 的牛逼之处了吧,不用优化性能就很不错,呵呵。
|
27
ChiangDi 2014-05-23 11:40:50 +08:00 via Android
楼主你这也叫测试。
|
28
skybr 2014-05-23 11:41:32 +08:00
不改算法, cPython要提高这东西的性能也挺容易的.
把那段fib改两行保存成pyx, 提速到node的1/10 cdef long _fibo(long n): return _fibo(n - 1) + _fibo(n - 2) if n > 1 else 1 fibo = lambda long n: _fibo(n) |
30
Sdhjt 2014-05-23 11:45:11 +08:00
这种测试怎么少得了Golang呢,来凑个热闹,以下是50位的测试结果:
node.js: 20365011074 real 3m34.670s user 0m0.000s sys 0m0.015s Golang: 20365011074 real 1m36.976s user 0m0.015s sys 0m0.015s 50位哦,40位速度太快,误差大。 |
31
phyng 2014-05-23 11:45:29 +08:00
果然这种帖子好赚金币啊
|
34
codingpp OP |
41
yueyoum 2014-05-23 12:01:23 +08:00
@codingpp
确实 递归很慢。 我并不是说递归不好, 而是 递归在 python 中很危险 1, 大量函数调用, 性能杀手 2, python没有尾递归优化,一点递归调用就会消耗大量的栈空间 3, 因为第2点,所以python有递归层数限制。超过这个限制,程序就会崩溃 所以,除非是少量的,你确定不会崩溃的, 否则别在python中用递归。 LZ 如果喜欢 递归, 看看 erlang, 用递归解决一切问题。 非常优雅。 |
45
codingpp OP |
48
yueyoum 2014-05-23 12:42:29 +08:00
|
49
jsonline 2014-05-23 12:45:19 +08:00
@yueyoum 优雅见仁见智,但是说实话没有 Python 易懂。另外为何命名不用全称要用缩写。 Num 为什么不是 Number。
|
50
davidjqq19 2014-05-23 12:48:19 +08:00
C语言:
unsigned int fibo(unsigned int n) { return n>1 ? fibo(n-1) + fibo(n-2) : 1; } int main() { printf("%u.\n", fibo(40)); return 0; } [*root*@/work/bash 12:47:45] : time ./a.out 165580141. real 0m0.844s user 0m0.839s sys 0m0.000s |
53
CMGS 2014-05-23 12:57:32 +08:00 via Android
我先占个坑……
1. |
54
vob636 2014-05-23 12:57:45 +08:00
话说你这种不公平的比较有什么意义么?node明显是有优化过程,而python以及php是基本上没有,你怎么就不用python里面的yield?而且node非阻塞原型……python都有实现……你就凭借这个fab函数,比较语言速度也没有这么比较的吧
|
55
NemoAlex 2014-05-23 12:59:16 +08:00
这种测试基本就是在比赛谁打 log 更快啊,有意义么?
|
56
CMGS 2014-05-23 13:02:04 +08:00 via Android
草,手机就是不好回复……
1. 你拿一个带jit的跟解释op code的比运算大丈夫? 2. python有个很magic的尾递归优化,裸cpython就算了 3. pypy预热足够的情况下……呵呵 4. 说白了时间换空间有什么好比的…… |
57
lm902 2014-05-23 13:05:22 +08:00 via iPhone
换成IronPython 试试
|
58
yueyoum 2014-05-23 13:08:19 +08:00
@jsonline
恩, 我对递归更习惯一点。 当时用 c++ 写一个 解数独程序, 递归很好写, 但是递归层数多了, 会 core dump。 最后还是花了点时间 改成循环。 我不是计算机专业的, 刚开始写C代码的时候,就写了很多递归。感觉很自然。 但我计算机专业的同学,当年交流的时候,他表示递归很难理解…… |
59
anchoretic 2014-05-23 13:17:15 +08:00
牛~
|
60
sandtears 2014-05-23 13:27:44 +08:00
python 跑斐波那契确实很慢,不过可以用 Ctypes 优化
|
61
est 2014-05-23 13:30:30 +08:00 2
for循环测试语言性能是月经话题。
|
62
madeye 2014-05-23 13:42:17 +08:00
tail call elimination 算是 JIT 最拿手的事情了… 只怪 Python 一直没有真正靠谱的 JIT 实现。
|
63
codingpp OP @binux
首先看到这个测试结果,你应该思考造成这些差异的主要原因是什么,而不是由于自己什么都不懂,各种语言实现太复杂,关联点太多,而认为这个问题你永远都无法理解,你应该有确认什么是主要因素的能力。 那不说各种语言了,就说同样的程序,在ie8和firefox中的差异怎么那么大 我在附言里就已经说了想了解 v8引擎是如何对递归、循环做优化的 |
64
binux 2014-05-23 14:13:13 +08:00 via Android
@codingpp 你在测试之前都不知道有什么会影响性能,比例是多少,用一个你自己都不知道什么会影响的用例,你要得出什么结论?
ok,在这个实际没用人用例子中,python是慢,然后呢,你导出任何有用结论吗? |
65
codingpp OP @binux
我在测试之前认为有差距,不过不大,但是测试结果却和我想的不一样,差距肯定是在什么关键地方,python和php只是普通的处理,nodejs做了优化。看到这个差异以后,然后我们就要去想这个问题在实际中有什么影响吗?不应该去搞清楚为什么吗。。。我不相信这个问题在数据分析计算的时候可以直接忽略。 函数调用,循环,变量,运算差异那么大,为什么python和php相差无几呢? 结论?那就是在某些场景使用语言的时候不用python了呗,或者考虑使用pypy,如果pypy也一样做了优化的话 |
67
codingpp OP @binux
看到这个差异以后,然后我们就要去想这个问题在实际中有什么影响吗?不应该去搞清楚为什么吗。。。 我实际上都不写c语言,我难道不该学c语言吗?我实际上不直接写数据结构,我难道不该学数据结构吗? 我之前还听过一些专科生嘲讽,你本科学那么杂的东西,实际中用的到吗,不能用到干嘛要学。。 回到这个问题。。实际中会写啊,递归、循环难道不是经常会用到。 |
68
binux 2014-05-23 14:58:29 +08:00 via Android
@codingpp 你程序递归占多少?这里几个语言都是实用语言,又不是实验学院语言,设计是有场景的,有目的的。
不看实际场景,测出来的结果,OK,我就是慢,但是在别人设计场景下人不care,和实际没有关系,你这个测试有半毛钱意义? |
69
codingpp OP |
70
hooluupog 2014-05-23 15:18:51 +08:00
@codingpp “那不说各种语言了,就说同样的程序,在ie8和firefox中的差异怎么那么大
我在附言里就已经说了想了解 v8引擎是如何对递归、循环做优化的”----------- 我个人的猜测:firefox有asm.js; ie8?这简直是欺负ie,应该找ie10,11来试试。至于v8,它用了JIT优化但也不至于像asm.js那么极端,那已经比的不是js本身的性能了,感兴趣的话可以试试google的pnacl下c/c++代码的实现版本,跑出的性能,应该比asm.js还要快,但还是会比直接在机器上跑c/c++慢一些。 p.s.建议: lz可以把你的测试程序改成尾递归的版本再测试下试试。 此外,用具有循环语法的非函数式语言去测试递归版本的斐波那契数列是最糟糕的测试,而且实际中这些语言的斐波那契数列实现也不会这么去写,所以这根本无法反映实际问题。为那种根本用不上的纯粹为了跑分而去优化的情况,大多数主流的编程语言编译器不会去干的,没有意义。所以,lz可以测试下其他的例子,不要再用递归版的斐波那契数列来做测试了。 |
71
glasslion 2014-05-23 15:19:51 +08:00
|
72
codingpp OP @glasslion
使用递归的例子最容易想出来的就是这个了~ 优化了就不知道在测什么了,我主要想搞清楚递归循环优化的问题,明白的人就会给出答案,不明白的又想装B刷存在感就来喷递归咯~ |
73
2ex 2014-05-23 15:53:55 +08:00
看大家秀各自都会很多语言,很有意思。
|
75
miser 2014-05-23 16:15:01 +08:00
这样的比较意义何在?
|
76
codingpp OP @miser
意义如下: 关于递归的问题,就是由于尾递归优化的问题,node.js做了优化而python没有,所以在使用递归的时候要注意,如何可以实现node.js那样使用python递归现在还不清楚。 关于循环的问题,现在还没有答案,你觉得这个答案也没有意义吗? |
77
miser 2014-05-23 17:13:55 +08:00
@codingpp 那也只能说这一项nodejs比py好,其它的呢? 下方直接说 ”node.js居然比python快了70多倍“这个不是在误导人吗? 按照 ”node.js居然比python快了70多倍”的说法,你这样的比较就有意义了?
|
78
notcome 2014-05-23 17:31:37 +08:00
大家有没有注意楼主似乎还在用 XP?
|
79
codingpp OP @miser
呵呵 循环累加 的确是快了70倍 有前提 有结果 怎么谈误导人?你自己测? 你如果知道为什么,就会在这里讲出来,你什么都不知道,上面在讨论什么你也看不明白,又想在这说两句当然就会喷这个东西无意义了~~ |
81
hooluupog 2014-05-23 18:18:29 +08:00
|
82
hooluupog 2014-05-23 18:22:33 +08:00
上面打错了,纠正:分别在node和pypy上测试。
|
83
codingpp OP |
84
hooluupog 2014-05-23 19:49:10 +08:00
@codingpp 我大意了,上面pypy还是比node慢,不过已经没有70倍那么多了。我说的JIT快是指你后面给的那个循环测试。
node和pypy估计现在都不支持尾递归优化(https://code.google.com/p/v8/issues/detail?id=457, ES6有提到未来打算支持,pypy应该还是不支持的)。 |
85
ruoyu0088 2014-05-23 20:09:39 +08:00
node.js和PHP支持长整数吗,那个while(i < 50000000)循环的结果是多少?
|
89
codingpp OP |
90
yakczh 2014-05-24 11:17:42 +08:00
我认为做个字符串解析或者json解析的比较更有实际意思 这个纯i++的操作完全看编译器的优化了
|
94
wuhx 2014-05-24 21:02:51 +08:00
@yueyoum 要展示我大erlang的优雅应该用这个经典栗子
#!/usr/bin/env escript fib(0) -> 0; fib(1) -> 1; fib(N) -> fib(N-1) + fib(N-2). main(_) -> io:format("~w~n",[fib(40)]). |
95
lm902 2014-05-25 10:28:05 +08:00
Python 3.3.0+ (win8app, Dec 27 2012, 21:34:06) [MSC v.1700 32 bit (Unknown)] on win32
Type "help", "copyright", "credits" or "license" for more information. >>> import datetime >>> def fibo(n): ... return fibo(n - 1) + fibo(n - 2) if n > 1 else 1 >>> print(datetime.datetime.now());print(fibo(40));print(datetime.datetime.now()) 2014-05-24 22:19:58.152036 165580141 2014-05-24 22:25:31.959224 >>> Python花了5分33.796812秒好吧,哪有你说的那么快 |
96
lm902 2014-05-25 10:38:45 +08:00
|
97
10iii 2014-05-25 10:44:25 +08:00
序言:LZ你这飞波算法明显有问题,fib(2)应该等于1啊喂.
首先:LZ的算法不是尾递归.尾递归要返回自身的调用,LZ这个经典算法返回的是个"+"调用.所以讨论不到尾递归优化. 其次:我觉得这种比较是有意义的,对相同的简单问题,使用相同的算法来解答,更容易分析速度之间的差异是由什么原因造成的,然后采取特定的策略. 大家有没有发现LZ提出了两个不同的测试,但讨论都集中在第一题递归上.原因就是第二个测试足够简单,就是循环,累加.多费口舌讨论显得愚蠢.于是很容易达成结论.那些要测试综合应用速度的同学们都还沒考虑到综合运用中牵扯的因素更多,比较结果会引发更多扯皮的讨论,最终是公婆都有理,谁也不信谁. 好几位同学从LZ使用原始的飞波算法这点来质疑LZ的算法能力,这种讨论方式试图以人废言,不好. 再来LZ这个讨论其实不能以语言来贴标签,应该以语言实现来贴标签. |
98
wangxinyu 2014-05-25 22:44:42 +08:00
Python慢是公认的
|
99
bigtan 2014-05-25 22:53:59 +08:00
def fib(n):
x=[0,1] for i in range(n): x=[x[1],x[0]+x[1]] return x[1] %%timeit fib(40) 10000 loops, best of 3: 19.9 µs per loop 装上scipy with MKL,单机矩阵运算跑得过MATLAB好么。你看我上面运算的单位,那是19.9微秒。 |
100
bigtan 2014-05-25 22:57:05 +08:00
%%time
...: fib(100000) ...: Wall time: 307 ms 其实还是代码写得不给力 |