4

我有几个想要阅读的日志文件。不失一般性,假设日志文件处理如下:

def process(infilepath):
    answer = 0
    with open (infilepath) as infile:
        for line in infile:
            if line.startswith(someStr):
                answer += 1
    return answer

因为我有很多日志文件,所以我想在这个问题上抛出多处理(我的第一个错误:我可能应该使用多线程;有人请告诉我为什么)

这样做时,我突然想到,任何形式的并行处理在这里都应该是无效的,因为我的 HDD 上只有一个读取头,因此只能读取一个文件。时间。事实上,在这种推理下,由于可能同时请求来自不同文件的行,读取头可能需要不时地显着移动,导致多进程方法比串行方法慢。所以我决定回到单个进程来读取我的日志文件。

有趣的是,我注意到小文件(<= 40KB)确实得到了加速,并且只有大文件(>= 445MB)才注意到预期的减速。

这让我相信 python 可能会以块的形式读取文件,其大小超过了我一次请求的一行。

Q1:那么底层的文件读取机制是什么?

Q2:优化从传统硬盘读取文件的最佳方法是什么?

技术规格:

  • python3.3
  • 5400rpm 传统硬盘
  • Mac OSX 10.9.2(小牛)
4

3 回答 3

2

观察到的行为是以下原因的结果:

  1. 缓冲IO
  2. 一种调度算法,用于决定读取 HDD 必要扇区的顺序

缓冲IO

根据操作系统和读取块的大小,整个文件可以放入一个块中,这就是在单个读取命令中读取的内容。这就是为什么较小的文件更容易阅读的原因

调度算法

较大的文件(文件大小 > 读取块大小)必须以block size块的形式读取。因此,当对多个文件中的每一个请求读取时(由于多处理),指针必须移动到 HDD 的不同扇区(对应于文件所在的位置)。这种重复的动作有两件事:

  1. 增加对同一文件的连续读取之间的时间
  2. 抛开读取扇区预测器,因为一个文件可能跨越多个扇区

如果在读取头可以提供来自同一文件的下一块行之前完成对一块行执行的计算,则连续读取同一文件之间的时间很重要,该过程只是等待直到另一块行变得可用。这是放缓的原因之一

丢弃读取预测器是不好的,原因与丢弃分支预测器不好的原因几乎相同。

由于这两个问题的综合影响,并行处理许多大文件会比串行处理要慢。当然,在许多行可以从 HDD 中读出blockSize之前处理完许多行时更是如此numProcesses * blockSize

于 2015-01-15T14:40:16.960 回答
1

另一个想法是分析您的代码

try:
    import cProfile as profile
except ImportError:
    import profile

profile.run("process()")
于 2014-10-26T13:16:41.357 回答
0

这是使用内存映射文件的示例

import mmap 
with open("hello.txt", "r+b") as f:
     mapf = mmap.mmap(f.fileno(), 0)
     print(mapf.readline()) 
     mapf.close()
    enter code here
于 2014-10-25T03:27:50.597 回答