[英]python - performance difference between the two implementations
How are the following two implementations have different performance in Python? 以下两个实现在Python中的性能如何?
from cStringIO import StringIO
from itertools import imap
from sys import stdin
input = imap(int, StringIO(stdin.read()))
print '\n'.join(imap(str, sorted(input)))
AND 和
import sys
for line in sys.stdin:
l.append(int(line.strip('\n')))
l.sort()
for x in l:
print x
The first implementation is faster than the second for inputs of the order of 10^6 lines. 对于10 ^ 6行量级的输入,第一种实现比第二种实现快。 Why so?
为什么这样?
>>> dis.dis(first)
2 0 LOAD_GLOBAL 0 (imap)
3 LOAD_GLOBAL 1 (int)
6 LOAD_GLOBAL 2 (StringIO)
9 LOAD_GLOBAL 3 (stdin)
12 LOAD_ATTR 4 (read)
15 CALL_FUNCTION 0
18 CALL_FUNCTION 1
21 CALL_FUNCTION 2
24 STORE_FAST 0 (input)
27 LOAD_CONST 0 (None)
30 RETURN_VALUE
>>> dis.dis(second)
2 0 SETUP_LOOP 48 (to 51)
3 LOAD_GLOBAL 0 (sys)
6 LOAD_ATTR 1 (stdin)
9 CALL_FUNCTION 0
12 GET_ITER
>> 13 FOR_ITER 34 (to 50)
16 STORE_FAST 0 (line)
3 19 LOAD_GLOBAL 2 (l)
22 LOAD_ATTR 3 (append)
25 LOAD_GLOBAL 4 (int)
28 LOAD_FAST 0 (line)
31 LOAD_ATTR 5 (strip)
34 LOAD_CONST 1 ('\n')
37 CALL_FUNCTION 1
40 CALL_FUNCTION 1
43 CALL_FUNCTION 1
46 POP_TOP
47 JUMP_ABSOLUTE 13
>> 50 POP_BLOCK
4 >> 51 LOAD_GLOBAL 2 (l)
54 LOAD_ATTR 6 (sort)
57 CALL_FUNCTION 0
60 POP_TOP
61 LOAD_CONST 0 (None)
64 RETURN_VALUE
first
is your first function. first
是您的第一个功能。 second
is your second function. second
是您的第二个功能。
dis
tells one of the reasons why the first one is faster. dis
讲述了第一个更快的原因之一。
Two primary reasons: 两个主要原因:
sorted
create only a internal list while sorting at the same time. sorted
仅创建一个内部列表,同时进行排序。 for
(on the Python VM), while the 1st version implicitly loops with imap
(over the underlaying structure in C). for
(在Python VM上)的列表,而第一个代码隐式地循环使用imap
(在C中的底层结构上)。 Anyways, why is StringIO in there? 无论如何,为什么StringIO在其中? The most straightforward and probably fastest way is:
最直接,可能最快的方法是:
from sys import stdin, stdout
stdout.writelines(sorted(stdin, key=int))
Do a step-by-step conversion from the second to the first one and see how the performance changes with each step. 从第二个步骤到第一个步骤进行逐步转换,看看性能如何随着每个步骤而变化。
l.append
with map(int, sys.stdin). l.append
替换map(int,sys.stdin)的for循环。 My guess is that this would give a significant speed-up. map
and l.sort
with imap
and sorted
. imap
和sorted
替换map
和l.sort
。 My guess is that it won't affect the performance, there could be a slight slowdown, but it would be far from significant. print
with print '\\n'.join(...)
. print
将for循环替换为print '\\n'.join(...)
。 My guess is that this would be another speed-up, but it would cost you some memory. Then, if you try THC4k's answer, it would probably be faster than all of the above, while being simpler and easier to read, and using less memory than 4 and 5. It has slightly different behaviour (it doesn't strip leading zeros from the numbers). 然后,如果您尝试THC4k的答案,它可能会比上述所有方法更快,同时更简单易读,并且使用的内存少于4和5。它的行为略有不同(它不会从中去除前导零。号码)。
Of course, try this yourself instead of trusting anyone guesses. 当然,请自己尝试,而不要相信任何人的猜测。 Also run
cProfile
on your code and see which parts are losing most time. 另外,在代码上运行
cProfile
,查看哪些部分浪费最多的时间。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.