Java:是不是存在磁盘与内存一样快的情况?
Posted
技术标签:
【中文标题】Java:是不是存在磁盘与内存一样快的情况?【英文标题】:Java: are there situations where disk is as fast as memory?Java:是否存在磁盘与内存一样快的情况? 【发布时间】:2013-03-19 17:59:38 【问题描述】:我正在编写一些代码来访问inverted index。 我有两个可互换的类,它们对索引执行读取。一个从磁盘读取索引,缓冲其中的一部分。另一个将索引完全加载到内存中,作为 byte[][](索引大小约为 7Gb)并从这个多维数组中读取。 人们期望在将整个数据保存在内存中的同时具有更好的性能。但我的测量表明,使用磁盘上的索引与在内存中使用索引一样快。 (在内存中加载索引所花费的时间不计入性能)
为什么会这样?有什么想法吗?
更多信息:我已经运行了启用 HPROF 的代码。无论是“在磁盘上”还是“在内存中”工作,最常用的代码并不是与读取直接相关的代码。此外,就我(有限的)理解而言,gc 分析器没有显示任何与 gc 相关的问题。
更新 #1:我已检测我的代码以监控 I/O 时间。似乎大多数内存寻道需要 0-2000ns,而大多数磁盘寻道需要 1000-3000ns。第二个指标对我来说似乎有点太低了。是由于Linux的磁盘缓存吗?有没有办法排除磁盘缓存以进行基准测试?
更新 #2:我绘制了对索引的每个请求的响应时间。内存线和磁盘线几乎完全匹配。我已经使用 O_DIRECT 标志进行了一些其他测试来打开文件(感谢 JNA!),在这种情况下,代码的磁盘版本(显然)比内存慢。所以,我的结论是“问题”是因为激进的 Linux 磁盘缓存,这非常了不起。
更新 #3:http://www.nicecode.eu/java-streams-for-direct-io/
【问题讨论】:
如果您接近最大堆大小,内存版本可能会因垃圾收集而变慢 - 您是否监控过 GC? 两种可能:1) 操作系统缓存磁盘读取 2) 代码性能实际上不受数据访问速度的限制。 即使被 GC RAM 减慢速度仍然比磁盘快(尽管取决于我们谈论的磁盘类型...)。 由于分配的堆比物理内存多,您也可能正在交换磁盘。没有分析很难分辨。Both working "on disk" or "in memory", the most used code it's NOT the one directly related to the reads.
所以......你有你的答案,不是吗?
【参考方案1】:
我想到了三种可能性:
操作系统已经通过其文件系统缓存将所有索引文件保存在内存中。 (请注意,我仍然预计会有开销。) 索引不是您正在测试的代码的瓶颈。 您的基准测试方法不太正确。 (很难做好基准测试。)对我来说,中间选项似乎最有可能。
【讨论】:
如果内存比磁盘快,如果代码对内存和磁盘执行相同数量的读取,那么内存版本不应该更快吗? @MatteoCatena:是的。但是,如果您不执行多次读取,而是花费大量时间做其他事情,那么差异可能会消失在噪音中。【参考方案2】:不,磁盘永远不会像 RAM 一样快(RAM 实际上比磁盘快 100,000 倍)。操作系统很可能正在为您将文件映射到内存中。
【讨论】:
你的回答能不能详细点?操作系统在 RAM 中缓存了一个 7GB 的文件,这对我来说似乎很奇怪。 当然我不是指整个文件,但是当您的进程未执行时,操作系统可能会在缓冲区中预加载,以预测您的读数。 有办法确认吗? 检查操作系统源代码(如果可用)。也许一些分析工具也可以给你更多的洞察力。问题是你确定你的问题在这里吗?。检查 Jon Skeet 的答案,特别是 nº2。 你知道在 Linux 的基准测试中排除磁盘缓存吗?以上是关于Java:是不是存在磁盘与内存一样快的情况?的主要内容,如果未能解决你的问题,请参考以下文章