首先,我无法重现结果。不知道SPOJ使用了哪些版本/设置。对于以下实验,使用PyPy 5.8.0和CPython 2.7.12。
作为测试用例,最大可能的输入文件大小约为
110MB
#create_data.py
print 10**6, 33
for i in xrange(10**6):
print 10**9
>> python create_data.py > input.in
正在运行
/usr/bin/time -v XXX solution.py < input.py
产量:
Interpreter MaximalResidentSize
PyPy: 278 Mb
CPython: 222 Mb
great article
关于他们的垃圾收集器及其与CPython的比较。
其次,我不相信SPJO网站上的数字。
system.stdin.read()
says
要读取文件内容,请调用f.read(size),它读取一定数量的数据并将其作为字符串返回。大小是可选的数字参数。当忽略大小或大小为负数时,将读取并返回文件的全部内容;
如果文件的大小是机器内存的两倍,这就是你的问题
在假设最坏的情况包括在他们的测试用例中的情况下,内存使用量至少应该是您使用的文件大小(110 MB)
std.stdin.read()
实际上,我不确定,所有的麻烦都值得使用
raw_input()
可能已经足够快了——我相信python会做正确的事情。CPython正常缓冲
stdout
和
stdin
(如果重定向到文件,则完全缓冲,或者控制台的行缓冲)并且必须使用命令行选项
-u
switch it off
.
但是如果你真的想确定,你可以使用
sys.stdin
-u强制stdin、stdout和stderr完全无缓冲。在…上
在重要的系统中,也将stdin、stdout和stderr放入
二进制模式。请注意
有内部缓冲
在xread中
文件对象迭代器(“for line-in
系统标准“
这意味着您的程序可能如下所示:
import sys
num, k = map(int,raw_input().split())
ans = 0
for line in sys.stdin:
if int(line)%k == 0:
ans += 1
print(ans)
这有一个很大的优势,即该变体仅使用大约7MB的内存。
另一个教训是,你不应该使用
sys.stdin.readline()
CPython CPython -u PyPy PyPy -u
original 28sec/221MB 25sec/221MB 3sec/278MB 3sec/278MB
raw_input() 29sec/7MB 110sec/7MB 7sec/75MB 100sec/63MB
readline() 38sec/7MB 130sec/7MB 5sec/75MB 100sec/63MB
readlines() 20sec/560MB 20sec/560MB 4sec/1.4GB 4sec/1.4G
file-iterator 17sec/7MB 17sec/7MB 4sec/68MB 100sec/62MB
有一些收获:
-
原始输入()
sys.stdin.read_line()
具有相同的性能
-
原始输入()
是缓冲的,但该缓冲区似乎与文件对象迭代器的缓冲区略有不同,后者的性能优于
至少对于此文件。
-
的内存开销
sys.stdin.readlines()
似乎很高,至少只要队伍很短。
-
文件对象迭代器在CPython和PyPy中有不同的行为,如果选项为
-u
用于:PyPy
同时关闭文件对象迭代器的缓冲(可能是错误?)。