for line in files:? 这个是读取大文件最快的方式吗
1
sjmcefc2 OP with open("file_name", 'r') as input:
for line in input: #process 这种真的非常慢啊 |
2
sjmcefc2 OP 100G 的文本。大家有好方式吗
|
3
swulling 2018-05-05 08:10:37 +08:00 via iPhone 2
|
4
clouduan 2018-05-05 08:16:11 +08:00 via Android
|
5
sjmcefc2 OP mmap 的话,如何逐行读取呢
|
6
NUT 2018-05-05 08:46:17 +08:00
java 用 RandomAccessFile 读流的时候判断是\n 就行
|
7
ltoddy 2018-05-05 08:50:40 +08:00
肯定是文件流啊,然后一部分一部分的读取.
fs.createReadStream() |
8
LosLord 2018-05-05 09:01:40 +08:00 via Android
Java 有个根据指针读取的类
|
9
sjmcefc2 OP python 的 mmap 用行读取的方法?这样行吗,但是感觉还是很慢
with open(STAT_FILE, "r+b") as f: m=mmap.mmap(f.fileno(), 0, prot=mmap.PROT_READ) while True: line=m.readline() if line == '': break print line.rstrip() 必须其他语言? |
10
sjmcefc2 OP 主要用来按行读取,然后 split,然后判断每个字段的编码,java 有这些? go 能满足?速度如何?
|
11
qsnow6 2018-05-05 09:16:23 +08:00
之所以慢,是因为要一次性把大文件读取到内存中。
使用流就行了,不是换语言能解决的 |
13
yunpiao111 2018-05-05 09:26:47 +08:00 via Android
如果是文本类的话 单机多核可以用 pyspark
|
14
notreami 2018-05-05 09:36:53 +08:00
不读,最快。
|
15
sjmcefc2 OP @yunpiao111 混合编码文本,单机多核心,pyspark 有逐行读取的案例?貌似在 api 里面没看到逐行读取的。。。。
|
18
swulling 2018-05-05 09:52:08 +08:00
你得先找到瓶颈啊,别瞎猜测是读取慢。来来来我给你验证下。
人工生成 1000 万行的文件 $ time python ./numbers.py > out python ./numbers.py > out 6.37s user 0.24s system 89% cpu 7.395 total 逐行读取,然后输出到 stdout,也就 7s 钟 你说『 42m 读了 900 万条』,那么瓶颈我觉得大部分是出在你的处理逻辑上,管读取什么事情? |
19
crayygy 2018-05-05 09:52:53 +08:00 via iPhone
之前遇到过要读 10G 的文本,后来采取了先排序,分割,筛选一次,剩下差不多 2G,最后再进一步分段读取
|
20
swulling 2018-05-05 09:53:11 +08:00
用 Profile 去分析下耗时,优化要先分析,后优化。不能脑子一拍,肯定是 Python 大文件读取慢,就开始吭叽吭叽优化这个...
|
21
dychenyi 2018-05-05 09:56:20 +08:00
如果没有严格的上下文依赖的话,那么分割大文件,多线程读取,分割成几块就用几个线程,处理边界,数据结构最后再合并。
个人有个 25G 的文件用 mmap+多线程读取 5 分钟之内。 一定要用 mmap,因为这是最快的读文件方式。 |
22
swulling 2018-05-05 09:57:07 +08:00
1000 万行,每行 100 个字符,总共 1.9G 文件。Python 使用 mmap 每行都输出一下,需要
python ./numbers.py > out 8.81s user 6.27s system 33% cpu 45.088 total 如果是 100G 文件,也不过几分钟而已 |
23
dychenyi 2018-05-05 09:58:12 +08:00
还有怎么按行读取,遇到\n 就是新行啊。自己处理。
|
24
sjmcefc2 OP |
25
tabris17 2018-05-05 10:20:59 +08:00
你要按行读取必须从头开始扫描啊,找出 N 个回车换行符,快不起来的
|
27
sjmcefc2 OP with open("test1.txt","r+b") as f:
mm = mmap.mmap(f.fileno(),0) while True: line = mm.readline() print line if line == '': break for v in line.split('^A'):#这个分界符不起作用了 print v m.close() |
29
ioth 2018-05-05 11:30:15 +08:00
什么类型“大”文件?后续怎么处理?
|
30
crb912 2018-05-05 11:58:37 +08:00 via Android
for line in input: 这个什么时候成了读取文件?
明明是遍历,open 的时候,文件就已经一次性读入内存了好吧。 |
33
sjmcefc2 OP @widewing ctrl+v+a,这个弄错了,不好意思。
@ioth 带有分隔符的文本文件,后续按照分隔符拆分。 @crb912 好吧,我错了,只是想问如何才能更快的遍历 @silymore print 最慢?那我去掉。现在 for line in input 和 mmap 一起运行,觉得 mmap 还没有前者快?错觉? with open("test1.txt","r+b") as f: mm = mmap.mmap(f.fileno(),0,prot=mmap.PROT_READ) while True: line = mm.readline() #print line if line == '': break for v in line.split('^A'): # print chardet.detect(v) #print chardet.detect(v)['encoding'] try: if(chardet.detect(v)['encoding'] in ['ascii','none','utf-8','GB2312','GBK','Big5','GB18030','windows-1252']): print v.decode(chardet.detect(v)['encoding']).encode('utf-8') else: print v.decode('utf-8').encode('utf-8') except: with open('error_mmap.txt','a') as e: e.write(line) m.close() |
34
ioth 2018-05-05 14:11:58 +08:00
纯文本文件处理,没什么区别吧,读写文件都是依赖操作系统。
|
35
dychenyi 2018-05-05 15:29:01 +08:00
@ioth “”常规文件操作需要从磁盘到页缓存再到用户主存的两次数据拷贝。而 mmap 操控文件,只需要从磁盘到用户主存的一次数据拷贝过程。说白了,mmap 的关键点是实现了用户空间和内核空间的数据直接交互而省去了空间不同数据不通的繁琐过程。因此 mmap 效率更高。“”
|
36
zhicheng 2018-05-05 16:54:28 +08:00
不知道也不要瞎讲,open 的时候文件并不会一次性读入内存。
|
37
fakevam 2018-05-05 17:39:28 +08:00
mmap 更慢,多想想就知道,page fault 明显更多了,而且是 major page fault
|
39
anjiannian 2018-05-05 18:50:32 +08:00
@sjmcefc2 python 里面,for line in input 就是逐行读取,print 慢
|
40
AX5N 2018-05-05 19:07:49 +08:00
把需求讲具体,不同需求下做法必定不同。有时候是直接把全部文件直接载入内存最快,但有时候不是。甚至有时候不能使用 python,python 一定会成为瓶颈
|
41
AX5N 2018-05-05 19:16:26 +08:00
@AX5N 按我经验
如果瓶颈在 IO 上的话,一次直接把所有内容都读进内存是最快的。 如果瓶颈在对内容细致地分析 /计算上的话,例如你要遍历 10G 文本里每个字节的话,那就必须得换语言才行。 如果瓶颈在于整体的处理速度的话,例如你要压缩一段文件。那这个就随便了,随便读取一部分处理完再继续读取就好。 |
42
pathbox 2018-05-05 19:27:26 +08:00 via iPhone
逐行读取
分块读取 用 shell 脚本应该会很快很快 |
43
livc 2018-05-05 19:31:30 +08:00
awk ?
|
45
AX5N 2018-05-05 19:48:54 +08:00
@sjmcefc2
100G 的文本有点夸张。 先说读取 假如你的硬盘是 HDD,按照 120M/s 来算的话,读取 10G 需要 850s ; 如果你的硬盘是 SSD,按照 450M/s 来算的话,需要 230s ; 无论你怎么来,无论你用什么办法,应该是不会慢过这个速度多少的,也不会快过这个速度多少。 再说处理 100G 的文本估计 10 亿行应该是有的吧,这个数量真的是太大了,单线程处理的话,python 速度慢的缺点会被暴露无遗。 所以建议你多进程、多线程来处理。 你这个每行之间没有联系,可以靠多线程来提高性能。如果碰上那种每行之间互有联系的,只能换 c++慢慢跑,python 绝对不行。 |
46
redsonic 2018-05-05 19:57:00 +08:00
像这类文件访存的效率问题都是处理时间和空间把戏。如果一个大文件要在短时间内随机访问上万次,用 mmap 应该是最好的。如果只是访问那么几次还不如 open write read。不过一般情况下无脑用 iostream 难道还不够快?
|
47
bfpiaoran 2018-05-05 23:11:17 +08:00
100G 不大 昨天我们这有读 6T 的 用的 seek 不知道速度怎么样。。。。
|
49
speedywind 2018-05-06 00:28:57 +08:00 via Android
不管什么语言,逐行读取肯定会慢一点,最快的方法是用 buff,
|
50
konakona 2018-05-06 00:29:35 +08:00
看要怎么处理,一般是分段分段(多少行到多少行,或者其他标识符号来记忆)提取后执行处理。
如果是要在 100GB 的文本里进行搜索……=v=呵呵呵呵呵呵呵呵 |
51
speedywind 2018-05-06 00:30:07 +08:00 via Android
一次读取 4k 的数据,因为一般现在分区都是 4k 对齐的
|
52
memorybox 2018-05-06 10:14:44 +08:00
这个问题其实有时候可以取巧处理的,比如用 parallel 工具,我觉得挺有意思,写了一篇文章,希望有帮助:
http://happy123.me/blog/2018/05/06/how-to-improve-performance-your-cmd-by-parallel/ |
54
BBCCBB 2018-05-06 12:36:39 +08:00
with open("file_name", 'r') as input:
for line in input: #process 我记得这种就是流式读取的啊??? |