【问题标题】:How to prevent C read() from reading from cache如何防止 C read() 从缓存中读取
【发布时间】:2013-05-03 18:31:47
【问题描述】:

我有一个程序用于在 RAID 配置中运行多个磁盘单元。 1 个进程同步(O_SYNC)使用write() 将随机数据写入文件。然后它将目录的名称放入共享内存队列中,其中第二个进程正在等待队列有条目以使用read() 将数据读回内存。

我似乎无法克服的问题是,当第二个进程尝试将数据读回内存时,没有一个磁盘单元显示读取访问。该程序有代码来检查读回的数据是否等于写入磁盘的代码,并且数据总是匹配的。

我的问题是,如何使操作系统(IBM i)在将数据写入磁盘时不缓冲数据,以便read() 系统调用访问磁盘上的数据而不是缓存中的数据?我正在做简单的吞吐量计算,read() 操作总是比write 操作快 10 倍以上。

我尝试使用O_DIRECT 标志,但似乎无法将数据写入文件。它可能与设置正确的对齐缓冲区有关。我也尝试过posix_fadvise(fd, offset,len, POSIX_FADV_DONTNEED) 系统调用。

我已经阅读了this 类似的问题,但没有找到解决方案。如果有帮助,我可以提供代码。

【问题讨论】:

  • 您可以关闭用户态文件缓存,例如在 C 中使用 setvbuf()。内核模式缓存可能需要重置内核参数,或运行创建大量内存块的代码,以便内核刷新其所有缓存。您所说的(IBM i)是指 IBM itanium AIX 吗?或者是什么? PS:直接 io 并不总是意味着没有缓存。系统可以直接写入,然后将数据保存在缓存中。操作系统设计人员非常重视使用内存来绕过 io 瓶颈。
  • @jimmcnamara - IBM i 是过去的 OS/400。它有一个名为 PASE for i 的特定环境,用于运行类 UNIX 软件。

标签: c unix caching io ibm-midrange


【解决方案1】:

我的想法是,如果您写入足够多的数据,那么根本就没有足够的内存来缓存它,因此必须将一些数据写入磁盘。

如果您想确保对文件的小写入工作正常,您也可以尝试写入另一个大文件(来自同一进程或不同的进程 - 例如,您可以启动类似 dd if=/dev/zero of=myfile.dat bs=4k count=some_large_number 的进程)强制其他数据填充缓存。

另一个“技巧”可能是“咀嚼”系统中的一些(更像是大多数)RAM - 只需分配一大块内存,然后一次写入其中的一小部分 - 例如,一个整数数组,您在循环中写入数组的每 256 个条目,每次向前移动一步 - 这样,您可以快速遍历所有内存,并且因为您正在连续写入所有内存,内存必须是常驻的。 [我在运行 VM 测试时使用这种技术来模拟“忙碌”的虚拟机]。

另一种选择当然是在 OS/文件系统驱动程序中使用缓存系统本身,但我会非常担心这样做 - 它几乎肯定会使系统减速到缓慢爬行,除非存在现有的禁用它的选项,您可能会发现很难准确/正确/可靠地进行操作。

【讨论】:

    【解决方案2】:

    ...在 RAID 配置中运行多个磁盘单元... 如何? IBM i 不允许程序访问硬件。您如何将 I/O 定向到任何特定的物理磁盘?

    回答: 写入/读取操作是针对 IFS 并行完成的,因此流文件管理器正在选择目标磁盘。通过有足够多​​的线程读取/写入,可以提高 SYSBASE 或 IASP 的繁忙度。

    ...所有磁盘单元都没有显示读取访问权限。 他们都没有?除非您在处于受限状态的系统上运行唯一的作业,否则其他任务将在磁盘上进行读取活动。系统是否划分为多个 LPAR?多个 ASP?我建议您可能正在监视该程序未写入的磁盘,因为 IBM i 处理物理 I/O,而不是程序。

    ANSWER 我想它们都没有一点儿夸张 - 我知道哪些磁盘属于 SYSBASE,并且这些磁盘不是 许多 读取请求的目标。我只是想为不熟悉 IBM i 的观众进行概括。在下图中,您将看到写入请求正在推动 % 繁忙度,但即使它们针对的是相同的文件,读取请求也不会。

    ...如何让操作系统 (IBM i) 在写入磁盘时不缓冲数据... 使用内存不足的主存储池来最大化分页,写入巨大的块数据,以保证系统和磁盘控制器缓存溢出并使用繁忙的机器,以便其他任务也需要磁盘 I/O。

    【讨论】:

    • 好的,所以您不会像攻击整个 iASP 一样尝试针对特定磁盘?运行这个过程的很多很多副本。这些机器从头开始设计用于处理大量 I/O,因此您将不得不努力让它流汗。使用大的、随机的数据块。
    • 是的,这是正确的——我的目标是整个 iASP 或 SYSBASE。正如您在图片中看到的那样,写入实际上充分推动了忙碌,但读取请求却没有。我认为 IBM i 正在缓存写入操作,因此读取是直接从缓存中完成的,而不是从磁盘中完成的。
    • 写了很多! :-) 为了超越缓存,您需要压倒它。如果您在文件中写入单个字母“A”,即使您运行一百个线程,它也很明显适合缓存。在更多线程中使用更大的数据块并压倒缓存。
    • 另外,请记住有三个独立的缓冲区/缓存。首先是单个程序使用的任何缓冲区。二是基础记忆。系统将尽其所能使用尽可能多的内存。如果访问足够频繁,则整个数据库文件通常会存在于物理内存中,并且没有其他东西需要内存页面。但磁盘控制器也有很大的缓存。关于控制器缓存如何与单个磁盘 I/O 相关的公开信息很少。操作系统本身不知道任何“磁盘”,只知道单独的磁盘池。
    猜你喜欢
    • 2012-03-31
    • 2010-09-09
    • 1970-01-01
    • 1970-01-01
    • 2011-12-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多