Linux C读写超大文件效率问题

xiaowhy 2011-08-24 07:16:20
各位高手帮忙看看,我这有几十G级别的比如60G文件需要读写,生成一些子文件,需要对原来文件的每一行进行解析;之前用fgets每一行的方法,客户对时间不是很满意;后来改用fork多个子进程,分段读取源文件,再生成不同的子文件,最后再把子文件合在一起,效果也不是很理想,逻辑不复杂,估计主要是IO的瓶颈;内存映射空间不够大吧,而且还要一行行的解析出来。
各位亲们不知有没有更好的办法啊?
...全文
2398 27 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
27 条回复
切换为时间正序
请发表友善的回复…
发表回复
2011-08-26
  • 打赏
  • 举报
回复
[Quote=引用 19 楼 xiaowhy 的回复:]
现在是有把文件分成几段,分子进程去读写,生成几个临时文件,再合并,直接用系统命令CAT,就是在合并的时候,速度又太慢,40G的文件要10分钟左右
[/Quote]
40GB 读 + 40GB 写 = 80GB I/O,平均下来有 136.5MB/s。

如果用的是单块硬盘这速度都快暴表了……你还想闹那样……
worldy 2011-08-25
  • 打赏
  • 举报
回复
[Quote=引用楼主 xiaowhy 的回复:]
各位高手帮忙看看,我这有几十G级别的比如60G文件需要读写,生成一些子文件,需要对原来文件的每一行进行解析;之前用fgets每一行的方法,客户对时间不是很满意;后来改用fork多个子进程,分段读取源文件,再生成不同的子文件,最后再把子文件合在一起,效果也不是很理想,逻辑不复杂,估计主要是IO的瓶颈;内存映射空间不够大吧,而且还要一行行的解析出来。
各位亲们不知有没有更好的办法啊?
[/Quote]

文件以缓冲的形式打开,应该能有所改善,但是,60G实在是太大了,一行行fgets才是占用时间的关键,应该在这上面想办法优化
xiaowhy 2011-08-25
  • 打赏
  • 举报
回复
多进程写同一个文件的话,又要去加锁啥的,估计也很慢
xiaowhy 2011-08-25
  • 打赏
  • 举报
回复
[Quote=引用 16 楼 hgxxx007 的回复:]

给你个建议,用空间换时间。

你看看你地文本内容长度最大是多少,建议设定一个值:256或者128

然后如果每行不足256个字节,补足256字节。进行文件定位的时候直接seek到指定行。

如果内容不是简单的就知道行数,那么建议再创建一个外部索引,进行读写文件的时候只是先查看索引然后在进行读写文件指定位置。

如果你的需求更复杂一点,需要在中间插入和删除行。建议把大文件拆分成小文……
[/Quote]
现在是有把文件分成几段,分子进程去读写,生成几个临时文件,再合并,直接用系统命令CAT,就是在合并的时候,速度又太慢,40G的文件要10分钟左右
jackyjkchen 2011-08-25
  • 打赏
  • 举报
回复
[Quote=引用 11 楼 hpsmouse 的回复:]

别急着优化程序,先算算现在的 I/O 速度是多少,要是已经达到了硬盘的速度上限程序再怎么优化都是白搭。

顺序读取大文件,内存映射其实没有直接读取快,不要碰到大文件就想着内存映射。
[/Quote]
至少对于Windows,内存映射的机制类似于异步IO,省去了同步等待ReadFile和WriteFile的时间,我做加密算法和Hash算法,处理大文件还是文件映射快
jngd 2011-08-25
  • 打赏
  • 举报
回复
你要知道你地程序读取的IO大部分都是废IO,

那就说明程序的优化空间或者架构优化空间还非常非常大。
jngd 2011-08-25
  • 打赏
  • 举报
回复
给你个建议,用空间换时间。

你看看你地文本内容长度最大是多少,建议设定一个值:256或者128

然后如果每行不足256个字节,补足256字节。进行文件定位的时候直接seek到指定行。

如果内容不是简单的就知道行数,那么建议再创建一个外部索引,进行读写文件的时候只是先查看索引然后在进行读写文件指定位置。

如果你的需求更复杂一点,需要在中间插入和删除行。建议把大文件拆分成小文件。然后外部任然通过一个索引文件进行索引。文件大小或者分片与否对上层不可见。
AnYidan 2011-08-25
  • 打赏
  • 举报
回复
[Quote=引用 11 楼 hpsmouse 的回复:]
别急着优化程序,先算算现在的 I/O 速度是多少,要是已经达到了硬盘的速度上限程序再怎么优化都是白搭。

顺序读取大文件,内存映射其实没有直接读取快,不要碰到大文件就想着内存映射。
[/Quote]

硬件问题硬件解决
暮雨晨舟 2011-08-25
  • 打赏
  • 举报
回复
不懂,帮顶!
jackyjkchen 2011-08-25
  • 打赏
  • 举报
回复
[Quote=引用 23 楼 hpsmouse 的回复:]

引用 18 楼 jackyjkchen 的回复:
至少对于Windows,内存映射的机制类似于异步IO,省去了同步等待ReadFile和WriteFile的时间,我做加密算法和Hash算法,处理大文件还是文件映射快

内存映射也是等到缺页的时候才去读文件的吧?也是同步的才对。

刚刚在 Linux 下分别用 MD5 和每行的字符个数统计都试了一遍,内存映射比直接分块读取是要慢那么一点点……
[/Quote]

操作系统区别,Windows下内存映射优势很明显
csuhanyong 2011-08-25
  • 打赏
  • 举报
回复
可以利用分页的思想去读吧?先读取100行显示出来,在101到200行
mLee79 2011-08-25
  • 打赏
  • 举报
回复
mmap 就节约一次从内核空间到用户空间之间的拷贝, 其他速度上差别不大. 如果用 mmap 慢了就比较奇怪了.

这东西你还是优化优化处理过程吧, 要快的时候就 fread , fwrite , mmap 信得过. 这种东西瓶颈都在IO上, 多线程/进程没啥用的...
2011-08-25
  • 打赏
  • 举报
回复
[Quote=引用 18 楼 jackyjkchen 的回复:]
至少对于Windows,内存映射的机制类似于异步IO,省去了同步等待ReadFile和WriteFile的时间,我做加密算法和Hash算法,处理大文件还是文件映射快
[/Quote]
内存映射也是等到缺页的时候才去读文件的吧?也是同步的才对。

刚刚在 Linux 下分别用 MD5 和每行的字符个数统计都试了一遍,内存映射比直接分块读取是要慢那么一点点,差距大概是几个 MB/s……
lamplet 2011-08-25
  • 打赏
  • 举报
回复
有一点现在都没弄明白,当时想通过setvbuf修改缓冲大小来提高效率,没有看到任何效果。后来改成每次读取大段内容却有效。不知道问题出在哪里。
lamplet 2011-08-25
  • 打赏
  • 举报
回复
我写过一个文件处理的程序,是顺序读取的。我不懂内存映射。只是自己把小段小段的读取,改成大段大段读取。减少文件读取次数,还是挺有效的。边界的问题,想办法处理下就好了。

不过,我也很想知道有什么经典的解决方法。老是做重复发明轮子的事情,浪费时间。还发明得比别人差,丢脸。
lightrat2009 2011-08-25
  • 打赏
  • 举报
回复
[Quote=引用 19 楼 xiaowhy 的回复:]
引用 16 楼 hgxxx007 的回复:

给你个建议,用空间换时间。

你看看你地文本内容长度最大是多少,建议设定一个值:256或者128

然后如果每行不足256个字节,补足256字节。进行文件定位的时候直接seek到指定行。

如果内容不是简单的就知道行数,那么建议再创建一个外部索引,进行读写文件的时候只是先查看索引然后在进行读写文件指定位置。

如果你的需求更复杂一点……
[/Quote]硬盘的存储速度也就这么慢吧!!!
2011-08-24
  • 打赏
  • 举报
回复
别急着优化程序,先算算现在的 I/O 速度是多少,要是已经达到了硬盘的速度上限程序再怎么优化都是白搭。

顺序读取大文件,内存映射其实没有直接读取快,不要碰到大文件就想着内存映射。
xiaowhy 2011-08-24
  • 打赏
  • 举报
回复
[Quote=引用 9 楼 aaajj 的回复:]

以前碰到过类似的问题,IO是很大的瓶颈。写文件的时候,可以设置个较大的缓存,减少写的次数
[/Quote]
这个我也有加啊,一般8K左右最好吧
aaajj 2011-08-24
  • 打赏
  • 举报
回复
以前碰到过类似的问题,IO是很大的瓶颈。写文件的时候,可以设置个较大的缓存,减少写的次数
jackyjkchen 2011-08-24
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 mangsong 的回复:]

引用 5 楼 qq120848369 的回复:
你的问题是I/O瓶颈,这个与海量数据处理没啥关系.

如果给预处理时间的话,那可以读大文件哈希到若干小文件,每个小文件可以直接映射到内存处理,这样的话利用两个线程并发遍历所有的文件,效率会高不少了,因为I/O问题已经不存在了 =,=


我想问下,我碰到过一个问题,对一个文件做MD5校验,当时我是用malloc申请的内存一次性读进来所有……
[/Quote]
md5支持分割校验,前提是你得有基础算法

md5基础算法一般是三个函数
init
process
done
其中process可以执行多次
加载更多回复(7)
内容概要:本文深入介绍了Linux文件指针的概念及其在文件操作中的重要性。首先解释了文件指针的作用,类似于书签,帮助程序准确定位文件中的读写位置,极大提高了文件操作的效率和灵活性。接着详细描述了文件指针的基本定义和与文件描述符的关系,指出文件指针是C语言层面的概念,具有更高的可移植性和易用性。文章还详细讲解了文件指针的操作函数,包括打开与关闭文件(fopen、fclose)、基本读写操作(fread、fwrite)、格式化读写(fprintf、fscanf)、字符与字符串读写(fgetc、fputc、fgets、fputs)以及文件定位操作(fseek、ftell、rewind)。此外,文中探讨了文件指针在日志记录、数据库系统和进程间通信等应用场景中的具体应用。最后,强调了文件指针使用中的注意事项,如错误处理、缓冲区管理和内存泄漏问题,确保程序的稳定性和高效性。 适合人群:具备一定编程基础,特别是对C语言和Linux系统有一定了解的开发人员,尤其是从事文件处理、系统编程和数据库开发的工程师。 使用场景及目标:①理解和掌握文件指针的基本概念和操作方法;②在日志记录、数据库操作和进程间通信等场景中,高效地进行文件读写操作;③通过合理的错误处理、缓冲区管理和内存管理,编写更健壮、高效的程序。 阅读建议:读者应结合实际编程案例,深入理解文件指针的工作原理和应用场景。建议在学习过程中多做实验,熟悉各种文件操作函数的使用方法,并注意错误处理和资源管理,以提升编程技能和解决实际问题的能力。
本PDF电子书包含上下两册,共1576页,带目录,高清非扫描版本。 作者: 毛德操 胡希明 丛书名: Linux内核源代码情景分析 出版社:浙江大学出版社 目录 第1章 预备知识 1.1 Linux内核简介. 1.2 Intel X86 CPU系列的寻址方式 1.3 i386的页式内存管理机制 1.4 Linux内核源代码中的C语言代码 1.5 Linux内核源代码中的汇编语言代码 第2章 存储管理 2.1 Linux内存管理的基本框架 2.2 地址映射的全过程 2.3 几个重要的数据结构和函数 2.4 越界访问 2.5 用户堆栈的扩展 2.6 物理页面的使用和周转 2.7 物理页面的分配 2.8 页面的定期换出 2.9 页面的换入 2.10 内核缓冲区的管理 2.11 外部设备存储空间的地址映射 2.12 系统调用brk() 2.13 系统调用mmap() 第3章 中断、异常和系统调用 3.1 X86 CPU对中断的硬件支持 3.2 中断向量表IDT的初始化 3.3 中断请求队列的初始化 3.4 中断的响应和服务 3.5 软中断与Bottom Half 3.6 页面异常的进入和返回 3.7 时钟中断 3.8 系统调用 3.9 系统调用号与跳转表 第4章 进程与进程调度 4.1 进程四要素 4.2 进程三部曲:创建、执行与消亡 4.3 系统调用fork()、vfork()与clone() 4.4 系统调用execve() 4.5 系统调用exit()与wait4() 4.6 进程的调度与切换 4.7 强制性调度 4.8 系统调用nanosleep()和pause() 4.9 内核中的互斥操作 第5章 文件系统 5.1 概述 5.2 从路径名到目标节点 5.3 访问权限与文件安全性 5.4 文件系统的安装和拆卸 5.5 文件的打开与关闭 5.6 文件的写与读 5.7 其他文件操作 5.8 特殊文件系统/proc 第6章 传统的Unix进程间通信 6.1 概述 6.2 管道和系统调用pipe() 6.3 命名管道 6.4 信号 6.5 系统调用ptrace()和进程跟踪 6.6 报文传递 6.7 共享内存 6.8 信号量 第7章基于socket的进程间通信 7.1系统调用socket() 7.2函数sys—socket()——创建插口 7.3函数sys—bind()——指定插口地址 7.4函数sys—listen()——设定server插口 7.5函数sys—accept()——接受连接请求 7.6函数sys—connect()——请求连接 7.7报文的接收与发送 7.8插口的关闭 7.9其他 第8章设备驱动 8.1概述 8.2系统调用mknod() 8.3可安装模块 8.4PCI总线 8.5块设备的驱动 8.6字符设备驱动概述 8.7终端设备与汉字信息处理 8.8控制台的驱动 8.9通用串行外部总线USB 8.10系统调用select()以及异步输入/输出 8.11设备文件系统devfs 第9章多处理器SMP系统结构 9.1概述 9.2SMP结构中的互斥问题 9.3高速缓存与内存的一致性 9.4SMP结构中的中断机制 9.5SMP结构中的进程调度 9.6SMP系统的引导 第10章系统引导和初始化 10.1系统引导过程概述 10.2系统初始化(第一阶段) 10.3系统初始化(第二阶段) 10.4系统初始化(第三阶段) 10.5系统的关闭和重引导

70,022

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧