三种写法,耗时从高到低,如下面代码所示,输出结果一样。各位大佬帮忙看下原因?
a = ''
for i in range(100000):
a = a+str(i)+'->'
b = ''.join([str(i)+'->' for i in range(100000)])
c = '->'.join(map(str, range(100000)))+'->'
输出结果:0->1->2->3->4->5->6->7->8->9...->99998->99999->
1
mxT52CRuqR6o5 2022-08-01 15:35:04 +08:00
for 相比 join 会生成大量的 string 中间状态影响性能吧
|
2
sujin190 2022-08-01 15:36:33 +08:00 1
你这分明是内存复制的问题,和 Python 毛关系没有吧,第一个慢的循环内存申请和复制量随着循环次数增加会指数增长,啥语言都会慢很多
|
3
Mohanson 2022-08-01 15:37:41 +08:00
思考下字符串加法.
|
4
metaquant 2022-08-01 15:37:50 +08:00
这个和 python 循环的效率无关,而是因为 python 中字符串是 immutable 的,每次拼接字符串都会产生复制一个新的字符串变量,开销较大,所以涉及大量字符串拼接时,正确的做法是使用第二和第三种方法中的 join , 所以你可以发现第二和第三种方法的差距很小。
|
5
sujin190 2022-08-01 15:38:58 +08:00
如果你在 c 或者 java 直接仅仅写这么一段也很快,那大概率是被编译器展开优化掉了,关掉编译优化再看看
|
6
wxf666 2022-08-01 15:42:11 +08:00 1
你换成 a += str(i)+'->' 就差不多一样了
|
7
qianc1990 2022-08-01 15:42:26 +08:00
第一个时间主要花在每次循环的字符串拼接上了
|
8
churchill 2022-08-01 15:44:06 +08:00
😄
``` function test() { a = '' for (let i=0; i<100000; i++) a = a+i+'->' return a } test() console.time("python sucks") test() console.timeEnd("python sucks") VM809:9 python sucks: 19.73193359375 ms ``` |
9
lingly02 2022-08-01 16:14:05 +08:00
function test2() {[...Array(10000).keys()].map((i)=>i+'->').join('')}
console.time("python sucks") test2() console.timeEnd("python sucks") VM1332:3 python sucks: 1.7998046875 ms |
10
nekochyan 2022-08-01 16:18:05 +08:00
第一个你是不是看错时间了,不是 7.8s 而是 0.78s ,我实测耗时 0.8s 左右
js 测试我跟楼上一样只需要 13ms 左右就完成循环了 |
11
wxf666 2022-08-01 16:38:33 +08:00
这个例子中,Google 花这么多钱搞的 V8 ,也没甩开 Python 多少啊?
这 8 楼 9 楼( 9 楼还少了个数量级)和楼主的没 JIT 的 Python 一比(第一个例子改成 += 就好),也没快多少啊 |
12
ipwx 2022-08-01 16:43:32 +08:00
无论什么语言,大量小字符串直接拼接都会有严重的性能问题。
|
13
aloxaf 2022-08-01 16:43:57 +08:00
见 wtrfpython: https://github.com/satwikkansal/wtfpython#section-miscellaneous
顺便本机测了一下,方法一 700 ms ,换 bytearray 只要 20ms a = bytearray() for i in range(100000): a.extend((str(i) + '->').encode()) a = a.decode() |
14
wyc9296 OP |
16
xgdgsc 2022-08-01 16:55:48 +08:00 via Android
就是很差的,julia 用 PythonCall.jl 用 julia 的 for 循环调用 python 函数随便比 python 快几个数量级
|
17
houzhiqiang 2022-08-01 17:03:10 +08:00
```python
import time def test(n: int = 100000): # return '->'.join([f'{x}' for x in range(n)]) + '->' return '->'.join(map(str, range(n))) + '->' start = time.time() test() print(f"used: {(time.time() - start) * 1000}ms") ``` cpython3.10.3 time python test.py used: 19.52505111694336ms python test.py 0.05s user 0.03s system 87% cpu 0.096 total pypy3.9-7.3.9 time pypy test.py used: 7.740020751953125ms pypy test.py 0.06s user 0.04s system 89% cpu 0.118 total #9 @lingly02 的代码 node v16.14.2 time node test.js python sucks: 3.757ms node test.js 0.05s user 0.02s system 95% cpu 0.069 total |
19
wxf666 2022-08-01 17:12:43 +08:00
@houzhiqiang 看起来日用差距不大,真要求性能,还是上 C/C++ 之类的吧,wasm 都没用(比如 squoosh 转码 avif ,比本地 avifenc 慢太多)
|
20
HankLu 2022-08-01 17:14:46 +08:00
判断一个字符串是否在一个巨大的文本里面怎么样最快?
|
21
houzhiqiang 2022-08-01 17:17:53 +08:00
#8 @churchill 的代码
node v16.14.2 time node test.js python sucks: 26.584ms node test.js 0.10s user 0.02s system 98% cpu 0.124 total #9 @lingly02 的代码 把他的 Array(10000)换成 Array(100000) node v16.14.2 time node test.js python sucks: 24.985ms node test.js 0.06s user 0.02s system 97% cpu 0.084 total @houzhiqiang |
22
houzhiqiang 2022-08-01 17:19:43 +08:00
|
23
wxf666 2022-08-01 17:30:43 +08:00
|
24
wxf666 2022-08-01 17:43:12 +08:00
|
25
churchill 2022-08-01 18:00:35 +08:00
这。。。我就是打个趣,代码是按楼主的第一种写法原封不动搬来的
性能这个事情 python 也还是要挣扎一下吗,大可不必 黑魔法的话 js 也有呀 warm 一下立杆见影 test() setTimeout(() => { console.time("python sucks") test() console.timeEnd("python sucks") }) |
26
lingly02 2022-08-01 18:25:52 +08:00 via iPhone
@houzhiqiang 上班摸鱼,看错数量了,😅
|
27
wxf666 2022-08-01 18:27:26 +08:00 2
|
28
Elaina 2022-08-01 18:30:50 +08:00
是字符串拼接影响效率,你把字符串拼接改成空操作,就没这么夸张了
|
30
zhuweiyou 2022-08-01 19:34:24 +08:00
字符串拼接的问题
|
31
xgdgsc 2022-08-01 20:02:56 +08:00
@wxf666 for 循环里先读取 memmap 的 array 里一个数,然后调用函数,这种情况反正用 julia 比 python 至少快一个数量级,我用几只不过想不起来具体快多少了,并不是说一定大于等于 3 才用几.
|
33
w3cll 2022-08-01 20:41:50 +08:00
蹲一个 PHP 的
|
34
pytth 2022-08-01 21:06:26 +08:00
```
<?php $starttime = explode(' ',microtime()); for($i=0; $i<100000; $i++){ echo $i.'<br/>'; } $endtime = explode(' ',microtime()); $thistime = $endtime[0]+$endtime[1]-($starttime[0]+$starttime[1]); $thistime = round($thistime,3); echo '用时'.$thistime; ?> ``` <img src="https://sc01.alicdn.com/kf/Ha0b06a519774459597cb42b339bd7ecbx.png" /> @w3cll |
36
wxf666 2022-08-02 00:34:25 +08:00
|
38
jinliming2 2022-08-02 08:38:11 +08:00 via iPhone
@pytth #34 你这个 echo 是流输出啊,不是字符串拼接,有点作弊了哦……
|
39
Anivial 2022-08-02 10:01:55 +08:00
一个提问贴能多这么多阴阳怪气的人也是没谁了,以后看见歪楼的就走,无语死
|