如果读文件的速度比处理的快怎么办

2020-02-21 21:59:55 +08:00
 23571113

我要处理一个大文件, 用的是 libuv(reactor 模型)来处理异步 I/O,但是一个问题是,我非阻塞分段读了文件之后(文件很大),放到线程池中做一些修改,然后按顺序非阻塞写到另外一个文件里.
问题一是 写文件是远程写,而读文件是本地读,这样非阻塞 I/O 会导致内存爆炸.
问题二是 既然是非阻塞 I/O 我怎么,输出怎么拼回去.

6046 次点击
所在节点    C++
40 条回复
learningman
2020-02-21 22:05:54 +08:00
disk cache
secondwtq
2020-02-22 01:42:56 +08:00
隐约觉得看到过有资料提过类似的情形: https://zeux.io/2019/04/20/qgrep-internals 从“First, the read speed and search speed can be substantially unbalanced.”开始

TLDR:作者实现了一个比 ag 和 ripgrep 等还快的代码检索工具(主要是加索引,ag 等一般是没索引的所以速度没法比),作者使用线程池来实现搜索,输入和输出都是单线程处理。在输入端用了一个队列,队列在数据超过一定量(也就是输入太快了)时会阻塞掉 push,在输出端使用了一个“ordered queue”,也就是 worker 线程在把结果交给输出线程时会附带位置顺序信息,输出线程只会在缓存里有下一块数据时才会写进去。
catror
2020-02-22 01:57:57 +08:00
1. 无论怎么读,你自己都可以控制读取速度的
2. 预分配文件,写的时候指定迁移即可,都有专门的函数
catror
2020-02-22 01:58:50 +08:00
@catror 迁移 --> 偏移
msg7086
2020-02-22 02:05:00 +08:00
分段读的时候检测一下内存占用,然后阻塞?
laminux29
2020-02-22 03:42:27 +08:00
建议题主尝试先不编程,而是在 Visio 上把流程图画一画,跟着流程走一走。

编程不仅是一门技术,更是一门艺术。
而艺术在于设计。

多设计,少 Coding,才是成为大神之道。
lihongming
2020-02-22 04:54:32 +08:00
参考 TCP 协议模型
FrankHB
2020-02-22 07:49:52 +08:00
@laminux29 要先设计是没错,但设计跟编程不冲突。只要是自己的设计,本质上总是可编程的。你看来只是要强调先不去拿代码实现罢了;然而画图真的就是给没有编程能力的外行人展示用的低效方法。
(严格意义上,图是可编程的,但拿 Visio 这种本来就不是为了这个目的设计的工具的方案,还不配实用。)
xenme
2020-02-22 07:56:11 +08:00
就是 buffer 的概念么

读的时候放到你的临时文件,临时文件达到一定大小,相当于 buffer 满了,得阻塞读了
boywhp
2020-02-22 09:00:44 +08:00
读得快写得慢 你不会暂停一会再读?
Cbdy
2020-02-22 09:02:03 +08:00
那你可以读慢一点
rapiz
2020-02-22 09:24:13 +08:00
不就是生产者消费者模型吗
reus
2020-02-22 09:31:09 +08:00
Michaelssss
2020-02-22 09:44:00 +08:00
你让我想起了 Linus 的读取 240GB/S 的硬盘😂过多占用内存总线
lqf96
2020-02-22 09:48:32 +08:00
我怎么感觉这其实就是 backpressure 的问题…
encro
2020-02-22 10:00:51 +08:00
@laminux29
@FrankHB

除了先画图,或者直接编程,有一种中间方法是先写注释,写注释过程过程理清楚,注释中说明为什么要这样做,然后写代码时填空即可,时间不多(必要),代码质量还高,且不容易出错。
一般我都会采用这种方式,偶尔涉及到比如多个系统多次交互,可能需要先画图。
abutter
2020-02-22 10:21:38 +08:00
就是乱序然后重组,发给多个线程工作的时候要带标识,例如序号,文件偏移地址之类的唯一标识,处理完后的线程将数据交给一个线程,这个线程负责数组排序重组然后写入。
abutter
2020-02-22 10:23:49 +08:00
问题 1,可以通过线程池的线程的数量限制获得最大的的处理能力,然后读取要根据数据完成的情况进行,而不是只要可以读就读。
问题 2,如上一个回答。
23571113
2020-02-22 11:11:31 +08:00
@catror 问题是文件修改过了,我没法知道偏移量了.
23571113
2020-02-22 11:25:17 +08:00
@secondwtq 大佬我觉得加同步队列的方法靠谱,毕竟我感觉写的慢的话,处理的再快也没用.
LZ 是小白,导师也很久没写代码了,准确来说需要我做一个备份软件,存储接各大云服务商的存储服务(例如阿里云 OSS,AWS S3),然后能够做到把不同文件的相似数据块给去掉. 导师给了我一个月时间, 我现在的情况是相关论文基本都看完了, 语言会 C++和一些非常基础的库,golang 稍微入门. 第一版计划让我跑在两个节点上,一个做在线去重,一个做离线去重,请问来的及吗?

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

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

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

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

© 2021 V2EX