alv*_*vas 14 python unicode performance ram file-io
如果RAM不是问题(我在服务器上接近200GB),更快地逐行读取或将所有内容读入RAM并访问它?每行将是一个大约200-500个unicode字符的字符串.每个文件有近200万行.
逐行
import codecs
for i in codecs.open('unicodefile','r','utf8'):
print i
Run Code Online (Sandbox Code Playgroud)
读入RAM
import codecs
for i in codecs.open('unicodefile','r','utf8').readlines():
print i
Run Code Online (Sandbox Code Playgroud)
Gar*_*ber 15
我在一个~1MB的字典单词文件中使用了cProfile.我读了3次同一个文件.第一个读取整个文件,只是在存储在缓存中的情况下甚至是在游戏领域.这是简单的代码:
def first_read():
codecs.open(file, 'r', 'utf8').readlines()
def line_by_line():
for i in codecs.open(file, 'r', 'utf8'):
pass
def at_once():
for i in codecs.open(file, 'r', 'utf8').readlines():
pass
first_read()
cProfile.run('line_by_line()')
cProfile.run('at_once()')
Run Code Online (Sandbox Code Playgroud)
以下是结果:
逐行:
366959 function calls in 1.762 seconds
Ordered by: standard name
ncalls tottime percall cumtime percall filename:lineno(function)
1 0.000 0.000 1.762 1.762 <string>:1(<module>)
1 0.000 0.000 0.000 0.000 codecs.py:322(__init__)
1 0.000 0.000 0.000 0.000 codecs.py:395(__init__)
14093 0.087 0.000 0.131 0.000 codecs.py:424(read)
57448 0.285 0.000 0.566 0.000 codecs.py:503(readline)
57448 0.444 0.000 1.010 0.000 codecs.py:612(next)
1 0.000 0.000 0.000 0.000 codecs.py:651(__init__)
57448 0.381 0.000 1.390 0.000 codecs.py:681(next)
1 0.000 0.000 0.000 0.000 codecs.py:686(__iter__)
1 0.000 0.000 0.000 0.000 codecs.py:841(open)
1 0.372 0.372 1.762 1.762 test.py:9(line_by_line)
13316 0.011 0.000 0.023 0.000 utf_8.py:15(decode)
1 0.000 0.000 0.000 0.000 {_codecs.lookup}
27385 0.027 0.000 0.027 0.000 {_codecs.utf_8_decode}
98895 0.011 0.000 0.011 0.000 {len}
1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects}
13316 0.099 0.000 0.122 0.000 {method 'endswith' of 'unicode' objects}
27 0.000 0.000 0.000 0.000 {method 'join' of 'str' objects}
14069 0.027 0.000 0.027 0.000 {method 'read' of 'file' objects}
13504 0.020 0.000 0.020 0.000 {method 'splitlines' of 'unicode' objects}
1 0.000 0.000 0.000 0.000 {open}
Run Code Online (Sandbox Code Playgroud)
一次全部:
15 function calls in 0.023 seconds
Ordered by: standard name
ncalls tottime percall cumtime percall filename:lineno(function)
1 0.000 0.000 0.023 0.023 <string>:1(<module>)
1 0.000 0.000 0.000 0.000 codecs.py:322(__init__)
1 0.000 0.000 0.000 0.000 codecs.py:395(__init__)
1 0.000 0.000 0.003 0.003 codecs.py:424(read)
1 0.000 0.000 0.014 0.014 codecs.py:576(readlines)
1 0.000 0.000 0.000 0.000 codecs.py:651(__init__)
1 0.000 0.000 0.014 0.014 codecs.py:677(readlines)
1 0.000 0.000 0.000 0.000 codecs.py:841(open)
1 0.009 0.009 0.023 0.023 test.py:13(at_once)
1 0.000 0.000 0.000 0.000 {_codecs.lookup}
1 0.003 0.003 0.003 0.003 {_codecs.utf_8_decode}
1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects}
1 0.001 0.001 0.001 0.001 {method 'read' of 'file' objects}
1 0.010 0.010 0.010 0.010 {method 'splitlines' of 'unicode' objects}
1 0.000 0.000 0.000 0.000 {open}
Run Code Online (Sandbox Code Playgroud)
从结果中可以看出,一次读取整个文件的速度要快得多,但是你冒着在文件中抛出MemoryError太大的风险.
没有什么能阻止你在你的机器上进行测试.我创建了一个文件,每行包含1M行,结果定时为
time python something.py > /dev/null
Run Code Online (Sandbox Code Playgroud)
分别为:
逐行:
real 0m4.878s
user 0m4.860s
sys 0m0.008s
Run Code Online (Sandbox Code Playgroud)
读入RAM:
real 0m0.981s
user 0m0.828s
sys 0m0.148s
Run Code Online (Sandbox Code Playgroud)
我尝试使用2M行时会遇到MemoryError,每行300个字符,但上面的内容表明读入RAM会更快.
看看OP发布的示例代码,我认为对Python的作用存在误解.
即:
"逐行阅读"
import codecs
for i in codecs.open('unicodefile','r','utf8'):
print i
Run Code Online (Sandbox Code Playgroud)
以上看起来像是逐行阅读.但是,Python将此解释为"将尽可能多的文件读入内存,然后将每个文件作为一行处理".所以实际上,上面的for循环将所有东西都读入内存.
"读入RAM"
import codecs
for i in codecs.open('unicodefile','r','utf8').readlines():
print i
Run Code Online (Sandbox Code Playgroud)
我相信以上几乎与上面的"逐行"示例相同.即,Python正在将它全部读入内存.
如果您想测试逐行性能,则需要"readline()"而不是"readlines()"或未指定的for循环,这可能意味着"readlines()".这在StackOverflow站点的其他地方有所说明.
另一个需要考虑的方面是文件系统缓冲.如果您针对同一文件运行相同的代码,则存在文件系统缓冲污染结果的风险.正如你所说,你有200GB的RAM,这足以缓冲足够的文件来影响运行结果.
您需要执行以下操作以确保清洁测试结果:
1)将大文件从已知源复制到新文件名.(Filesystem不必是COW文件系统.)2)刷新文件系统缓存3)对文件运行第一次测试.4)删除文件5)将文件从源重新复制到另一个新文件名.6)刷新文件系统缓存7)对新文件运行第二次测试.
这将为您提供更准确的文件加载时间测试.
如果要同时将整个文件加载到内存中,filehandle.read(要读取的字节)是否可能提供更快的块读取文件内容?
在任何一种情况下,供参考:
http://docs.python.org/2/tutorial/inputoutput.html
| 归档时间: |
|
| 查看次数: |
735 次 |
| 最近记录: |