Java:是否存在磁盘和内存一样快的情况?

Java:是否存在磁盘和内存一样快的情况?,java,io,bigdata,Java,Io,Bigdata,我正在写一些代码来访问一个。 我有两个可以互换的类,它们对索引执行读取。从磁盘读取索引,缓冲部分索引。另一个将索引完全加载到内存中,作为字节[](索引大小约为7Gb),并从这个多维数组中读取。 人们希望在将整个数据存储在内存中的同时获得更好的性能。但我的测量表明,在磁盘上使用索引和在内存中使用索引一样快。 (在内存中加载索引所花费的时间不计入性能) 为什么会这样?有什么想法吗 进一步信息:我已经运行了启用HPROF的代码。无论是“在磁盘上”还是“在内存中”,最常用的代码都不是与读取直接相关的代码

我正在写一些代码来访问一个。 我有两个可以互换的类,它们对索引执行读取。从磁盘读取索引,缓冲部分索引。另一个将索引完全加载到内存中,作为字节[](索引大小约为7Gb),并从这个多维数组中读取。 人们希望在将整个数据存储在内存中的同时获得更好的性能。但我的测量表明,在磁盘上使用索引和在内存中使用索引一样快。 (在内存中加载索引所花费的时间不计入性能)

为什么会这样?有什么想法吗

进一步信息:我已经运行了启用HPROF的代码。无论是“在磁盘上”还是“在内存中”,最常用的代码都不是与读取直接相关的代码。另外,就我(有限的)理解而言,gc分析器没有显示任何与gc相关的问题

更新#1:我已经检测了我的代码以监视I/O时间。看起来,内存上的大多数寻道需要0-2000ns,而磁盘上的大多数寻道需要1000-3000ns。第二个指标对我来说似乎有点太低了。是由于Linux的磁盘缓存吗?是否有一种排除磁盘缓存以进行基准测试的方法

更新#2:我已将每个索引请求的响应时间绘制成图表。内存线和磁盘线几乎完全匹配。我还使用O_DIRECT标志做了一些其他测试来打开文件(感谢JNA!),在这种情况下,代码的磁盘版本(显然)比内存慢。所以,我的结论是“问题”是因为积极的Linux磁盘缓存,这是相当惊人的


更新#3

不,磁盘的速度永远比不上RAM(实际上,磁盘的RAM速度是磁盘的100000倍)。操作系统很可能正在为您映射内存中的文件。

我想有三种可能性:

  • 操作系统已经通过其文件系统缓存将所有索引文件保留在内存中。(请注意,我还是希望有一笔开销。)
  • 索引不是您正在测试的代码的瓶颈
  • 你的基准测试方法不太正确。(做好基准测试可能非常困难。)

中间的选项对我来说似乎最有可能。

如果接近最大堆大小,内存版本可能会因垃圾收集而变慢-您监控过GCs吗?有两种可能性:1)操作系统缓存磁盘读取2)代码性能实际上不受数据访问速度的限制。即使通过GC RAM变慢,速度也会更快而不是磁盘(尽管这取决于我们谈论的是哪种类型的磁盘…)。由于分配的堆比物理内存多,您也可能正在交换磁盘。如果没有分析,很难判断。
既可以在“磁盘”上工作,也可以在“内存”中工作,最常用的代码不是与读取直接相关的代码。
所以。。。答案是否定的?如果内存比磁盘快,并且代码对内存和磁盘的读取次数相同,那么内存版本不应该更快吗?@MatteoCatena:是的。但是如果你不经常阅读,但是你花了很多时间做其他事情,那么差异可能会消失在噪音中。你能在回答中更详细一些吗?我觉得很奇怪,操作系统在RAM中缓存了一个7GB的文件。当然,我不是指整个文件,但当您的进程没有执行时,操作系统可能会在缓冲区中预加载,预期您的读数。有没有办法确认这一点?检查操作系统源代码(如果可用)。也许一些分析工具也能给你更多的洞察力。问题是你确定你的问题在这里吗?。检查Jon Skeet的答案,特别是nº2。您知道在Linux上进行基准测试时排除磁盘缓存吗?