我想比较处理流作为过滤器(即得到一点,处理,冲洗),反对啜饮(即获取所有信息,然后处理)的效果。
然而,当我运行下面的两个代码时,我得到了可比较的结果。我期待在slurp版本中获得更糟糕的结果。
如上所述,代码片段是否会执行任何不同的操作?如果它们是等价的,我怎样才能调整其中一个来测试滤波器/啜食差异?
我正在测试脚本:
jot 100000000 | time python3 dont_slurp.py > /dev/null
jot 100000000 | time python3 slurp.py > /dev/null
Jot
生成从1到x的数字。代码片段只是对行进行计算。
过滤器:
import sys
lineno = 0
for line in sys.stdin:
lineno += 1
print("{:>6} {}".format(lineno, line[:-1]))
啜食:
import sys
f = sys.stdin
lineno = 0
for line in f:
lineno += 1
print('{:>6} {}'.format(lineno, line[:-1]))
答案 0 :(得分:0)
首先,您的代码示例没有按您的想法进行。所有f = sys.stdin
都将f
设置为相同的文件句柄。行for line in f:
和for line in sys.stdin:
功能相同。
你想要的是这个:
import sys
lineno = 0
for line in sys.stdin.readlines():
lineno += 1
print('{:>6} {}'.format(lineno, line[:-1]))
readlines()
返回一个列表,文件中每行一个元素。我相信它是不是一个生成器,所以你得到完整的列表。文件句柄本身充当生成器,一次为您提供一行。
您应该会看到与readline()
的性能差异。
然而,答案是"哪个更好?"是"它取决于"。当您逐行读取时,您正在进行系统调用,这反过来会导致操作系统以块的形式从磁盘读取文件内容。这些块可能大于平均线的大小,并且块可能被缓存。这意味着有时你会占用磁盘,花费大量时间,有时你会点击缓存,花费很少时间。
当您一次读取所有内容时,您会立即将文件中的每个字节加载到内存中。如果您有足够的可用内存来容纳所有文件内容,那么这需要与逐行版本完全相同的时间。在这两种情况下,基本上只是按顺序读取整个文件所需的时间,只需要一些开销。
不同之处在于您没有足够的可用内存来容纳整个文件。在这种情况下,您将读取整个文件,但部分内容会被虚拟内存系统交换回磁盘。然后,当您访问该特定行时,他们必须再次被拉入。
确切耗费了多少时间取决于正在使用的内存量,系统上正在进行的其他活动量等等,因此无法对其进行量化。
在出现问题之前,您真的不应该担心这种情况。如果您的程序太慢,那么在代码中执行更自然的操作并且只担心性能。