再看文件读写性能问题

来源:互联网 发布:淘宝企业店铺是c店吗 编辑:程序博客网 时间:2024/06/05 09:38

摘选和总结了一下网友们的观点。

http://www.dnbcw.com/biancheng/c/dpgo42576.html


软件上所有对磁盘的访问 最终都变成硬盘驱动程序对硬盘设备的访问。
硬盘是慢速设备 对他写入的时候 如果没有cache 那么每次对他访问 他只有确切的完成后才允许驱动程序再访问它,但是等待它完成io操作是很费时的 因此引入了cache 每次驱动程序将数据写入硬盘的cache 因为cahce有一定容量 因此不用等待硬盘完成io操作 就可以继续写入 而另一方面硬盘从cache中取数 然后一次次的执行io操作 这样cache就像个fifo cache越大 容量越多 驱动程序写入被阻塞的可能性就越少 但是硬盘毕竟慢 cache也只是权宜之计 如果在cache被填满前不再有请求了 那么8m的cache就比2m的cache能缓存更多的数据 自然速度更快 但是如果你的io请求数据量非常大 那么8m也好 2m也好 总会被快速填满 届时2者就没什么分别了 因此cache大小对性能的影响只在轻量级和中量特别有效果。

 

硬盘狂转很正常.程度问题.读写大量数据的时候肯定得狂转,但是实际的读写次数却未必一样.简单说如果能用较少的读写次数完成较多的工作,那么硬盘负荷会降低并且程序的速度也会加快.同样是4k的数据一次写出会比写出4k次的1字节会快非常多.相对的,减少硬盘读写次数意味着消耗更多的内存来作为缓冲.

传说中c++标准库里的stream实现...这在高强度的读写操作时是个瓶颈.涉及大量文件操作的acm题向来会提示不要用c++标准库里的istream/ostream/iostream/ifstream/ofstream/fstream.(需要到源文档验证)

 

虽然从硬盘寿命来说,写入的次数的确是越少越好,但是对效率来说却并非如此
实际操作多些就能发现,一个大文件并不是以越少次数写入就越快
每次写入数据的最佳大小要依照硬盘缓存大小来决定
如果写的是一个要在别人机器上使用的通用程序,那么就要考虑不确定的缓存
现在硬盘一般缓存为4m,考虑到还有其他程序在使用缓存(比如qq这个磁盘缓存强盗),所以一般将数据分块大小定为1m左右为好
再者就是要在写入磁盘的函数之后马上加一句等待系统的指令,这样在硬盘完成写入过程后程序才会继续,这在提高效率上非常重要

然后就能发现,这样写入大文件时速度绝对比一次写入要快多而且也不会让系统卡(当然你有啥算法在占用cpu的话就不能算数…… otl)

 

首先unsigned long long 这个类型 我记得在vc下没有 在gcc上有 代表64位长的数据类型 在32位机器上使用64位数据类型的话,结果就是编译器对64位数据长的数据进行两次访问。

cahce的问题我上面解释过了 对于高压力的io操作 cache的大小作用没那么特别明显了 但是对于轻量和中量的访问 cache越大 阻塞硬盘驱动程序对硬盘的访问的机会越少,速度自然越快。

软件上所有对磁盘的访问 最终都变成硬盘驱动程序对硬盘设备的访问。
硬盘是慢速设备 对他写入的时候 如果没有cache 那么每次对他访问 他只有确切的完成后才允许驱动程序再访问它,但是等待它完成io操作是很费时的 因此引入了cache 每次驱动程序将数据写入硬盘的cache 因为cahce有一定容量 因此不用等待硬盘完成io操作 就可以继续写入 而另一方面硬盘从cache中取数 然后一次次的执行io操作 这样cache就像个fifo cache越大 容量越多 驱动程序写入被阻塞的可能性就越少 但是硬盘毕竟慢 cache也只是权宜之计 如果在cache被填满前不再有请求了 那么8m的cache就比2m的cache能缓存更多的数据 自然速度更快 但是如果你的io请求数据量非常大 那么8m也好 2m也好 总会被快速填满 届时2者就没什么分别了 因此cache大小对性能的影响只在轻量级和中量特别有效果。

 

另外就是实际的性能还和很多因素相关 比如你用的读写函数 像fread、fwrite这样的 都在用户层实现了自己的io缓冲 你读 实际上它会读1块(和文件系统的块的含义不同) 你写1字节 它只把数据写入内存的io缓冲里 而不实际写入
另外就是文件系统 因为文件系统的基本单位不是字节 而是块 具体的块大小 每个文件系统都不同
比如你用readfile直接读取1字节 那么文件系统可能会读取1个块的数据 这样文件系统自己也有一个缓存
再往下是内核提供的通用io缓存 这个缓存和具体文件系统无关 只要有对io的访问 就把数据缓存在自己维护的基于页的缓存里 最后就是硬件级别的cache了 其中文件系统和内核的通用缓存 这2个设计操作系统的实现 每个操作系统的具体实现方式可能不同。

引用第13楼ravenex于2007-05-31 15:26发表的  :
那在32位机器上使用64位的数据类型并不会比使用32位的数据类型来执行固定的循环操作要快,是这样的吗?小的还是有点不明白,还得多多修炼才行

多数游戏的封包里,单个文件都不会达到4m吧?那研究一下cache的最佳使用经验还是有意义。不然也不会出现b树等的数据结构专门着眼于硬盘读写的特点


不 实际上会快 因为你无形中对2个4字节的访问放在一个循环里做了 这个优化叫循环展开 这种优化通常编译器做不到 是人为的优化 有数据显示展开16-32(也就是一个循环内,每次处理64-128字节,每次4字节)能够提高性能。(主要是充分利用了指令流水线)

我认为专门研究硬盘的cache意义不大 因为从你的程序到实际写入硬盘 中间过了好几层 而且不能只把硬盘当作你一个人使用的对象 因此优化的时候主要不是研究针对硬盘cache的优化 当然除非你跨过所有的软件层 直接和驱动打交道(数据库通常会这么做)

 

 

原创粉丝点击