python 纯加减运算慢

2016-04-02 14:28:46 +08:00
 simon4545

Python 代码: import time a=time.time() i=0 for i in xrange(95550000): i +=100 i -=100 print i print time.time()-a

运行结果: 95549999 15.253000021

得到的不是 95550000 编译成了 Pyc 也一样的结果

但换成 Node.js 会快 100 倍都不止 var a=new Date(); var i; for(i = 0; i < 95550000; ++i) {    i += 100; i -= 100; } console.log(i) console.log((new Date())-a)

结果: 95549999 0.21799993515

我试了 pypy,性能和 node.js 接近

5308 次点击
所在节点    Python
28 条回复
koykoi
2016-04-02 15:01:29 +08:00
这种 hot spot 代码不正是 JIT 的优势吗
clino
2016-04-02 15:17:23 +08:00
nodejs 应该和 pypy 一样都用了 jit 吧?
clino
2016-04-02 15:26:31 +08:00
我这里的结果是
-在循环里算两个+-耗时 15.1 秒
-在循环里算一个+耗时 9.89 秒
-循环里 pass 耗时 3.72 秒
BOYPT
2016-04-02 15:27:47 +08:00
大概是因为 python 里面的整数是 immutable 的对象,你这样的操作就是重复生成对象和回收对象,所以效率较低;大概使用 numbers 模块里面功能会有改善。
josephok
2016-04-02 16:01:50 +08:00
用 python3 试试
zwpaper
2016-04-02 16:09:22 +08:00
本来就应该是 9554999 的吧?
python3 是:
95549999
10.84103798866272
Zzzzzzzzz
2016-04-02 16:09:46 +08:00
光这个 xrange 就得两三秒.
要改进性能的话把这段代码抽出来上 Cython , i = 0 前面加 cdef long, 秒变毫秒级.
simon4545
2016-04-02 16:18:36 +08:00
python3 执行也是一样的,而且还要更久一点
有没有 jit 居然相差那么大
realpg
2016-04-02 19:15:31 +08:00
1. python 内 xrange(3)的结果是 0,1,2
2. 这种场景就是 JIT 的性能强悍啊

realpg@TestingServer17:/tmp/demo$ python python.py
95549999
15.7798058987
realpg@TestingServer17:/tmp/demo$ pypy python.py
95549999
0.574637174606
realpg@TestingServer17:/tmp/demo$ /usr/local/php5/bin/php php.php
95550000
7.9244079589844
realpg@TestingServer17:/tmp/demo$ /usr/local/php7/bin/php php.php
95550000
3.8246450424194


python2.7 python.py 代码同楼主

php.php 代码
<?php
$time_start = microtime(true);
for ($i=0;$i<95550000;$i++) {
$i+=100;
$i-=100;
}
$time_end = microtime(true);
$time = $time_end - $time_start;
echo "{$i}\n{$time}\n";
slixurd
2016-04-02 19:21:49 +08:00
居然连 microbench 之类的工具都没用,在这裸写。。。。
bigtan
2016-04-02 19:24:52 +08:00
用 Python ,执行效率一般难以成为瓶颈,因为,他可以通过别的优化手段轻松的达到 C-level 的执行效率。
theoractice
2016-04-02 20:27:43 +08:00
@bigtan 42.7ns ?表示震惊
zhuangzhuang1988
2016-04-02 22:01:59 +08:00
没 jit 就得这么慢, 虽然里面有一些 intern 缓存优化。但是对这些纯计算的没啥鸟用。。
bigtan
2016-04-02 22:04:09 +08:00
@theoractice 有缓存的可能,你可以看 best case 。 42.7ns*24.87=1061.9ns ,不过也足够惊人的了。
est
2016-04-02 22:21:06 +08:00
其实 python 加减乘除不慢, for 比较慢。
mathgl
2016-04-02 22:30:28 +08:00
这种代码, jit 稍微优化一下就是常数了。
Zzzzzzzzz
2016-04-02 22:37:08 +08:00
@theoractice
@bigtan

倒没那么夸张, Cython 现在对 range 和 xrange 有优化, 会直接转成循环, 以前那种 for i from 0<=i<95550000 的方言被废了, 然后默认的编译参数又是-O2, 直接把循环这部分给优化掉了,等于什么都没做直接给 i 赋值了
SlipStupig
2016-04-03 01:35:18 +08:00
每次+一次就是内存申请一次啊,而且你用 for 就变成了直接 sum 回快多了 sum(xrange(95550000)),时间明显减少太多了

3 function calls in 1.140 seconds

Ordered by: standard name

ncalls tottime percall cumtime percall filename:lineno(function)
1 0.000 0.000 1.140 1.140 test.py:1(<module>)
1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects}
1 1.140 1.140 1.140 1.140 {sum}
simon4545
2016-04-03 02:47:55 +08:00
@est 我后面也试了,正如你所说的一样。
能请教一下原因么?
pynix
2016-04-03 04:27:50 +08:00
不可变对象,一直在申请和释放内存。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/268116

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX