如何避免物理磁盘 I/O
Posted
技术标签:
【中文标题】如何避免物理磁盘 I/O【英文标题】:How to avoid physical disk I/O 【发布时间】:2011-11-01 20:31:04 【问题描述】:我有一个通过网络写入大量数据的进程。假设它在机器 A 上运行,并通过 NFS 在机器 B 上转储大约 70-80GB 的文件。进程 1 完成并退出后,我的进程 2 运行机器 A 并通过 NFS 从机器 B 获取此文件。整个周期的瓶颈就是这个庞大的数据文件的读写。我怎样才能减少这个 输入/输出时间?我能否以某种方式将数据加载到内存中,以便在进程 1 退出后也可供进程 2 使用?
我很感激这方面的想法。谢谢。
编辑:由于进程 2 直接从网络“读取”数据,是否会更好 先本地复制数据,再从本地磁盘读取? 我的意思是 (网络读取时间) > (cp 到本地磁盘) + (从本地磁盘读取)
【问题讨论】:
为什么不将文件保存在机器 A 上? 你能将数据直接从进程 1 传送到进程 2 吗? 【参考方案1】:如果您想将数据加载到内存中,则需要 70-80 GB 的 RAM。
最好的办法是在系统 A 上附加一个本地存储(硬盘驱动器)以将该文件保存在本地。
【讨论】:
【参考方案2】:显而易见的答案是减少网络写入 - 这似乎可以成倍地节省您的时间并提高可靠性 - 将 any 文件复制到另一台机器只是为了将其复制回来似乎没有什么意义,因此为了更准确地回答您的问题,我们需要更多信息。
【讨论】:
【参考方案3】:这种方法有很多网络和 IO 开销。因此,您可能无法进一步降低延迟。
-
由于文件超过 80 GB,创建一个进程 1 将写入的 mmap,稍后进程 2 可以从中读取 - 不涉及网络,仅使用机器 A - 但仍有 IO 开销是不可避免的。
更快:两个进程可以同时运行,您可以使用信号量或其他信号机制,其中进程 1 可以指示进程 2 文件已准备好读取。
最快的方法:让进程 1 创建一个共享内存并与进程 2 共享。每当达到限制(可以加载到内存中的最大数据块,取决于您的 RAM 大小)时,让进程 1 向进程 2 发出信号可以读取和处理数据 - 只有当文件/数据实际上可以逐块处理而不是 80GB 的一大块时,此解决方案才可行。
【讨论】:
共享内存大小有上限。我认为默认值为 32MB。有什么方法可以通过我的应用程序增加它? 您可以通过ipcs -l
查看限制,您可以通过/etc/sysctl.conf
更改限制。设置kernel.shmmax=<value>
并执行sysctl -p
。您只能以 root 身份执行此操作。虽然_sysctl()
可以从您的应用程序中实现此功能,但不推荐使用此功能。【参考方案4】:
无论你使用mmap
还是普通的read
/write
应该没什么区别;无论哪种方式,一切都通过文件系统缓存/缓冲区发生。最大的问题是 NFS。提高效率的唯一方法是将中间数据本地存储在机器 A 上,而不是通过网络将其发送到机器 B,然后再将其拉回。
【讨论】:
这是一个很好的观点。有可以用作本地存储的安全挂载吗?我可能在“cwd”中没有写权限..【参考方案5】:使用tmpfs 将内存用作(临时)文件。
使用mbuffer 和netcat 可以简单地从一个端口中继到另一个端口,而不存储中间流,但仍允许流以不同的速度发生:
machine1:8001 -> machine2:8002 -> machine3:8003
在 machine2 上配置如下作业:
netcat -l -p 8002 | mbuffer -m 2G | netcat machine3 8003
这将允许最多缓冲 2 gig 的数据。如果缓冲区填满 100%,则 machine2 将开始阻塞来自 machine1 的读取,从而延迟输出流而不会失败。
当 machine1 完成传输后,第二个 netcat
将一直存在,直到 mbuffer 耗尽
【讨论】:
【参考方案6】:-
您可以使用 RAM 磁盘作为存储空间
NFS 很慢。尝试使用其他方式将数据传输到另一台 PC。示例 - TCP/IP 流。
另一种解决方案 - 您可以使用内存数据库(示例为 TimesTen)
【讨论】:
以上是关于如何避免物理磁盘 I/O的主要内容,如果未能解决你的问题,请参考以下文章