如何快速向文件中写入 1 亿个 ip?

2022-04-09 15:49:53 +08:00
 lsk569937453

背景:需要向一个文件中写入 1 亿个 ip ,最快的方法是什么?机器配置是 mac book,双核 cpu,8GB 内存。 我用 java 实现了一个多线程的写入,发现速度慢的要死(写入时间 5 分钟以上)。有没有人推荐一下速度写入大文件的方法,或者其他语言快速写入大文件的方案。

7812 次点击
所在节点    程序员
66 条回复
Buges
2022-04-09 15:52:16 +08:00
mmap
Itesting
2022-04-09 15:52:38 +08:00
感觉减少磁盘 io ,内存多放点
gam2046
2022-04-09 15:53:02 +08:00
写文件,不需要多线程,瓶颈必然在 IO ,简单的增加缓冲区即可。
ChaosesIb
2022-04-09 15:54:56 +08:00
最快的话……VFS
其次内存映射
写入不要多线程,只会降低速度
winnie2012
2022-04-09 15:57:08 +08:00
楼上都说了,写内存,减少 IO
pengtdyd
2022-04-09 15:57:09 +08:00
kafka 为啥这么快?利用了顺序写入!
xiri
2022-04-09 15:57:19 +08:00
IO 操作多线程一般没什么效果,硬盘都是连续大量写入时要更快。
你需要的是缓存方案,简单点就是先往内存中存着,再从内存中整块整块写入硬盘
Puteulanus
2022-04-09 16:08:25 +08:00
拼成一个大文本一次写进去,拿 PHP 试了下 5 秒不到,别搞花里胡哨的了,内存要不够就拆成几次
GeruzoniAnsasu
2022-04-09 16:17:13 +08:00
不知道 OP 能不能意识到这问题背后有多少坑……

1. 多线程读写同一个 io 很蠢且不会起作用。因为文件系统 api 的作用仅仅是给内核发个通知,让内核去 copy 数据。多线程和单线程调用同一个 file descriptor 上的读写不会有什么区别
2. 1 亿个 ip 不应该放在一个普通文件里,这么大规模的数据为什么不用数据库管理?
3. ipv4 原本仅仅只是一个 4 字节的整数,ipv6 也只有 16 字节,不知道 OP 准备存的是什么,不会是字符串吧
4. 这种规律排布的数据压缩比本来可以非常大的,考虑压缩了吗



最快的方法是开一个 file map (mmap) ,然后在 mmap 给你提供的「内存」里存数据。你往里写的时候写的是内存,然后 OS 内核会自动帮你把内存页交换到文件系统上。

但这个映射也还是可以继续优化的,因为默认内存页很小且物理内存不连续。如果你想,用上巨型页和手撸的 dma 驱动可以更快
HankLu
2022-04-09 16:24:01 +08:00
不知道,没写过
lsk569937453
2022-04-09 16:25:18 +08:00
@Puteulanus 卧槽,1 亿个 IP 拼的字符串,你内存没爆吗?
zmxnv123
2022-04-09 16:37:43 +08:00
一个 ip 占一个 int ,也就 4 byte ,搞什么花里胡哨的。

用 python 写了个最暴力的, 也就 20s...,还用的 wsl 跑的,如果用原生 windows 估计更快。

代码
```
with open("./ip.txt", "w") as fp:
for i in range(0, 10000):
for j in range(0, 10000):
fp.write(str(i * j) + "\n")

```
结果
```
➜ Desktop time python test.py
python test.py 19.75s user 0.81s system 99% cpu 20.586 total
```
lsk569937453
2022-04-09 16:38:04 +08:00
看了下楼上的回复,用 mmap 实现了一把,单线程 50s 写完。还能继续提升这个速度吗?比方说多线程 mmap?
lsk569937453
2022-04-09 16:39:34 +08:00
@zmxnv123 你生成一个合法的 ip 啊,你写个 str(i*j)这。。。
xiri
2022-04-09 16:42:00 +08:00
@lsk569937453 不懂为什么会爆内存,一亿个 IP 的原始数据也就四亿字节,380MB 左右,就算用字符串,全部按 3*4+3+1 (四段+三个点+换行符)计算 16 亿字节,也就 1.5GB 左右
zmxnv123
2022-04-09 16:47:40 +08:00
@lsk569937453 i * j 可以理解为一个 int 啊,就是一个 ip
shawnsh
2022-04-09 16:54:32 +08:00
@lsk569937453 好奇老哥为啥说提升性能就上多线程?多线程不是万能解药
lsk569937453
2022-04-09 17:05:45 +08:00
@zmxnv123 好思路。我以前只是写 ip 字符串。如果把所有的 ip 拼成一个字符串一次写入,用多久。
Juszoe
2022-04-09 17:10:14 +08:00
别惦记你那多线程啦,首先,为什么要写这么多 ip 到文件,其次,如果是连续 ip 可以考虑压缩
lsk569937453
2022-04-09 17:10:53 +08:00
@shawnsh 因为我单线程写花了 100s,多线程写花了 50s 。你能说性能没有提升吗?

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/845892

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX