高磁盘使用率是否意味着更快的文件 read/write 操作?
Does high disk usage mean faster file read/write operations?
我正在编写一个 python 脚本,我在其中逐行读取一个大约 5 GB 的大文件,对每一行进行一些修改,然后将其写入另一个文件。
当我使用函数file.readlines()读取输入文件时,我的磁盘使用率达到~90%并且磁盘速度达到+100Mbps(我知道这种方法不应该用于大文件).
我没有测量上述情况下的程序执行时间,因为我的系统变得无响应(内存已满)。
当我像下面这样使用迭代器时(这就是我在代码中实际使用的)
with open('file.csv', 'r') as inFile:
for line in inFile:
我的磁盘使用率仍然低于 10%,速度低于 5 Mbps,程序完成一个 5 GB 文件的执行大约需要 20 分钟。如果我的磁盘使用率很高,这个时间会不会更低?
此外,读取 5 GB 是否真的需要大约 20 分钟,逐行处理,对每一行进行一些修改,最后将其写入一个新文件,还是我做错了什么?
我不明白的是为什么程序在执行 io 操作时没有充分利用我的系统的潜力。因为如果是这样,那么我的磁盘使用率应该更高,对吧?
这仅取决于您用于读取文件的缓冲区大小。
让我们看一个例子:
您有一个包含 20 个字符的文件。
您的缓冲区大小为 2 个字符。
那么整个阅读时间至少要使用10次系统调用
系统调用是一个非常昂贵的操作,因为内核必须切换执行上下文。
如果你有一个 20 个字符大小的缓冲区,你只需要 1 个系统调用,因此只需要一个内核陷阱。
我假设第一个函数只是在内部使用了更大的缓冲区。
您不仅需要文件的 RAM,还需要输入和输出缓冲区以及修改文件的第二个副本。这很容易使您的 RAM 不堪重负。
如果您不想在 for 循环中读取、修改和写入每一行,您可能希望将一些行组合在一起。这可能会使 reading/writing 更快,但代价是更多的算法开销。在一天结束时,我会使用逐行方法。
喂!
吕
我不认为你的主要问题是读取文件,因为你正在使用 open(),相反我会检查你在这里做什么:
make some modifications in each of the lines, and then write it to
another file.
因此,请尝试在不对另一个文件进行修改/写入修改的情况下读取该文件,以了解您的系统仅读取该文件需要多少时间。
以下是我在阅读 this,, and this
后在我的环境中进行的测试
首先,创建了一个 1.2GB 的文件:
timeout 5 yes "Ergnomic systems for c@ts that works too much" >> foo
我没有使用 dd 或 truncate,这会导致读取文件时出现内存错误。
现在一些 I/O 测试读取文件,这是一个已经优化的操作,就像@Serge Ballesta 提到的:
#!/usr/bin/python
with open('foo') as infile:
for line in infile:
pass
print 'file readed'
$ time python io_test.py
file readed
real 0m2.647s
user 0m2.343s
sys 0m0.327s
使用 open() 更改缓冲选项:
# --------------------------------------NO BUFFERING
with open('foo','r',0) as infile:
for line in infile:
pass
print 'file readed'
$ time python io_test.py
file readed
real 0m2.787s
user 0m2.406s
sys 0m0.374s
# --------------------------------------ONE LINE BUFFERED
with open('foo','r',1) as infile:
for line in infile:
pass
print 'file readed'
$ time python io_test.py
file readed
real 0m4.331s
user 0m2.468s
sys 0m1.811s
# -------------------------------------- 70 MB/s
with open('foo','r',700000000) as infile:
for line in infile:
pass
print 'file readed'
$ time python io_test.py
file readed
real 0m3.137s
user 0m2.311s
sys 0m0.827s
为什么不应该使用 readlines:
with open('foo') as f:
lines = f.readlines()
for line in lines:
pass
$ time python io_test.py
real 0m6.428s
user 0m3.858s
sys 0m2.499s
在Python中逐行读取文件已经是一个优化的操作:Python从磁盘加载一个内部缓冲区并将其逐行提供给调用者。这意味着行标识已经由 Python 解释器在内存中完成。
通常,当磁盘访问是限制因素、内存限制或处理器限制时,处理可以是磁盘 IO 限制。如果您使用某些网络,它可以是网络 IO 绑定或远程服务器绑定,仍然取决于限制因素是什么。当您逐行处理文件时,进程不太可能受内存限制。要确定磁盘 IO 是否是限制部分,您可以尝试使用系统复制实用程序简单地复制文件。如果大约需要20分钟,那么这个过程是磁盘IO绑定的,如果快得多,那么线路上的修改就不能忽略了。
无论如何,在内存中加载一个大文件总是一个坏主意...
我正在编写一个 python 脚本,我在其中逐行读取一个大约 5 GB 的大文件,对每一行进行一些修改,然后将其写入另一个文件。
当我使用函数file.readlines()读取输入文件时,我的磁盘使用率达到~90%并且磁盘速度达到+100Mbps(我知道这种方法不应该用于大文件).
我没有测量上述情况下的程序执行时间,因为我的系统变得无响应(内存已满)。
当我像下面这样使用迭代器时(这就是我在代码中实际使用的)
with open('file.csv', 'r') as inFile:
for line in inFile:
我的磁盘使用率仍然低于 10%,速度低于 5 Mbps,程序完成一个 5 GB 文件的执行大约需要 20 分钟。如果我的磁盘使用率很高,这个时间会不会更低?
此外,读取 5 GB 是否真的需要大约 20 分钟,逐行处理,对每一行进行一些修改,最后将其写入一个新文件,还是我做错了什么?
我不明白的是为什么程序在执行 io 操作时没有充分利用我的系统的潜力。因为如果是这样,那么我的磁盘使用率应该更高,对吧?
这仅取决于您用于读取文件的缓冲区大小。
让我们看一个例子:
您有一个包含 20 个字符的文件。
您的缓冲区大小为 2 个字符。
那么整个阅读时间至少要使用10次系统调用
系统调用是一个非常昂贵的操作,因为内核必须切换执行上下文。
如果你有一个 20 个字符大小的缓冲区,你只需要 1 个系统调用,因此只需要一个内核陷阱。
我假设第一个函数只是在内部使用了更大的缓冲区。
您不仅需要文件的 RAM,还需要输入和输出缓冲区以及修改文件的第二个副本。这很容易使您的 RAM 不堪重负。 如果您不想在 for 循环中读取、修改和写入每一行,您可能希望将一些行组合在一起。这可能会使 reading/writing 更快,但代价是更多的算法开销。在一天结束时,我会使用逐行方法。 喂! 吕
我不认为你的主要问题是读取文件,因为你正在使用 open(),相反我会检查你在这里做什么:
make some modifications in each of the lines, and then write it to another file.
因此,请尝试在不对另一个文件进行修改/写入修改的情况下读取该文件,以了解您的系统仅读取该文件需要多少时间。
以下是我在阅读 this,
首先,创建了一个 1.2GB 的文件:
timeout 5 yes "Ergnomic systems for c@ts that works too much" >> foo
我没有使用 dd 或 truncate,这会导致读取文件时出现内存错误。
现在一些 I/O 测试读取文件,这是一个已经优化的操作,就像@Serge Ballesta 提到的:
#!/usr/bin/python
with open('foo') as infile:
for line in infile:
pass
print 'file readed'
$ time python io_test.py
file readed
real 0m2.647s
user 0m2.343s
sys 0m0.327s
使用 open() 更改缓冲选项:
# --------------------------------------NO BUFFERING
with open('foo','r',0) as infile:
for line in infile:
pass
print 'file readed'
$ time python io_test.py
file readed
real 0m2.787s
user 0m2.406s
sys 0m0.374s
# --------------------------------------ONE LINE BUFFERED
with open('foo','r',1) as infile:
for line in infile:
pass
print 'file readed'
$ time python io_test.py
file readed
real 0m4.331s
user 0m2.468s
sys 0m1.811s
# -------------------------------------- 70 MB/s
with open('foo','r',700000000) as infile:
for line in infile:
pass
print 'file readed'
$ time python io_test.py
file readed
real 0m3.137s
user 0m2.311s
sys 0m0.827s
为什么不应该使用 readlines:
with open('foo') as f:
lines = f.readlines()
for line in lines:
pass
$ time python io_test.py
real 0m6.428s
user 0m3.858s
sys 0m2.499s
在Python中逐行读取文件已经是一个优化的操作:Python从磁盘加载一个内部缓冲区并将其逐行提供给调用者。这意味着行标识已经由 Python 解释器在内存中完成。
通常,当磁盘访问是限制因素、内存限制或处理器限制时,处理可以是磁盘 IO 限制。如果您使用某些网络,它可以是网络 IO 绑定或远程服务器绑定,仍然取决于限制因素是什么。当您逐行处理文件时,进程不太可能受内存限制。要确定磁盘 IO 是否是限制部分,您可以尝试使用系统复制实用程序简单地复制文件。如果大约需要20分钟,那么这个过程是磁盘IO绑定的,如果快得多,那么线路上的修改就不能忽略了。
无论如何,在内存中加载一个大文件总是一个坏主意...