在 HD 中进行数据密集型读写的最佳实践是啥?
Posted
技术标签:
【中文标题】在 HD 中进行数据密集型读写的最佳实践是啥?【英文标题】:Which are the best practices for data intensive reading and writing in a HD?在 HD 中进行数据密集型读写的最佳实践是什么? 【发布时间】:2011-06-15 06:15:10 【问题描述】:我正在开发一个 C++ 应用程序(在 Linux 机器中运行),它在读取日志文件和将派生结果写入磁盘方面非常密集。我想知道优化这类应用程序的最佳做法是:
哪些操作系统调整可提高性能? 哪些编程模式可以提高 IO 吞吐量? 预处理数据(转换为二进制、压缩数据等)是否有用? 分块/缓冲数据是否有助于提高性能? 我应该注意哪些硬件功能? 哪些做法最适合分析和衡量这些应用程序的性能? (在这里表达我所缺少的担忧)是否有一本很好的读物可以让我了解这方面的基础知识,以便我可以根据我的问题调整现有的专业知识?
谢谢
【问题讨论】:
将数据保存在缓冲区中,尽量少写,太慢了。 【参考方案1】:压缩肯定有很大帮助,而且比调整操作系统要简单得多。查看Boost.iostreams 库中的gzip
和bzip2
支持。不过,这会对处理器造成影响。
从time
命令开始测量这些类型的作业。如果系统时间与用户时间相比非常高,那么您的程序会花费大量时间进行系统调用。如果挂钟(“真实”)时间比系统时间和用户时间高,则它正在等待磁盘或网络。 top
命令显示程序的 CPU 使用率明显低于 100%,这也是 I/O 瓶颈的标志。
【讨论】:
我们通过使用zcat bigfile.gz | ourprogram
与 ourprorogram < bigfile
获得大约 3 倍的加速。以 zcat 进行解压缩的 CPU 使用率较高、我们的程序不阻塞 IO 以及大(10Gb)文件的初始 gzip 压缩为代价。 bzip2 给我们的性能比 zcat 低——可能是因为解压花费了更多时间——但这一切都取决于你花费多少 CPU 时间与解压。【参考方案2】:
1) 检查磁盘的扇区大小。 2) 确保磁盘已进行碎片整理。 3) 读取“本地”数据到您为提高缓存局部性所做的最后一次读取(缓存由操作系统执行,许多硬盘驱动器也具有内置缓存)。 4) 连续写入数据。
为了提高写入性能,将数据块缓存在内存中,直到达到扇区大小的倍数,然后启动异步写入磁盘。在确定数据已被写入(即同步写入)之前,不要覆盖当前正在写入的数据。双重或三重缓冲在这里会有所帮助。
为了获得最佳读取性能,您可以双缓冲读取。因此,假设您在读取时缓存了 16K 块。将第一个 16K 从磁盘读取到块 1。启动将第二个 16K 异步读取到块 2。开始处理块 1。当您完成块 1 时,同步块 2 的读取并开始异步读取到块 1将第 3 个 16K 块放入第 1 块。现在处理第 2 块。完成同步读取第 3 个 16K 块后,启动第 4 个 16K 块的异步读取到第 2 块并处理第 1 块。冲洗并重复,直到处理完所有数据。
如前所述,您必须读取的数据越少,从磁盘读取所花费的时间就越少,因此可能值得读取压缩数据并花费 CPU 时间扩展读取的每个块。在写入之前同样压缩块将节省您的磁盘时间。这是否真的成功将取决于您处理数据的 CPU 密集程度。
此外,如果对块的处理是不对称的(即处理块 1 的时间可能是处理块 2 的 3 倍),则考虑对读取进行三倍或更多缓冲。
【讨论】:
【参考方案3】:获取有关您将要写入/读取的卷的信息,并创建与卷特征匹配的缓冲区。例如10 * 集群大小。
缓冲有很大帮助,因为它可以最大限度地减少你必须做的写入量。
【讨论】:
【参考方案4】:正如这里所说,您应该检查块的大小。您可以使用 stat 系列函数来执行此操作。 在 struct stat 中,此信息位于字段 st_blksize。
第二件事是函数 posix_fadvise(),它为操作系统提供有关分页的建议。您告诉系统您将如何使用文件(甚至是文件的片段)。您可以在手册页上找到更多信息。
【讨论】:
【参考方案5】:在 Windows 上,使用带有 FILE_FLAG_SEQUENTIAL_SCAN 和/或 FILE_FLAG_NO_BUFFERING 的 CreateFile() 而不是 fopen() - 至少是为了立即写入此返回而不是等待数据刷新到磁盘
【讨论】:
以上是关于在 HD 中进行数据密集型读写的最佳实践是啥?的主要内容,如果未能解决你的问题,请参考以下文章