据我所知,Mappedbytebuffer有几个好处,例如:
它将用户空间内存地址映射到内核空间内存地址,这样在读取文件时,就避免了从内核空间到用户空间的内存复制
在第一次读取文件中的一个片段(例如缓冲区中从0到100的偏移量)之后,这个片段将被缓存在内存中,因此当第二次从缓冲区读取同一个片段时,您是直接从内存中读取,而不是从磁盘中读取。
我的问题是:
我以上的理解正确吗?
如果我的理解是正确的,那么当你只读一次(不要再读一次,这样它就不会从内存中读了)时,使用filechannel.read(buffer,position)和mappedbytebuffer.get(byte[],offset,length)是否相同?
对于对文件的随机访问(不重复读取同一个文件),filechannel是否更有效,因为mappedbytebuffer将占用它映射的内存,而filechannel不需要内存?
使用mappedbytebuffer和简单地将整个文件加载到内存中有什么区别?mappedbytebuffer的好处是它使用jvm堆外的内存,所以不涉及gc?
最佳答案
让我逐一回答你的问题。
据我所知,Mappedbytebuffer有几个好处,例如:
它将用户空间内存地址映射到内核空间内存地址,这样在读取文件时,就避免了从内核空间到用户空间的内存复制
在第一次读取文件中的一个片段(例如缓冲区中从0到100的偏移量)之后,这个片段将被缓存在内存中,因此当第二次从缓冲区读取同一个片段时,您是直接从内存中读取,而不是从磁盘中读取。
你的陈述不是无效的。
不过,重要的是不要错过简单的事实。文件数据的访问总是涉及缓存(except when it does not)。如果缓存中的内存映射页映射到您的地址空间,则需要使用filechannel额外的内存副本。
如果我的理解是正确的,那么当你只读一次(不要再读一次,这样它就不会从内存中读了)时,使用filechannel.read(buffer,position)和mappedbytebuffer.get(byte[],offset,length)是否相同?
不,filechannel.read(buffer,position)包含额外的内存拷贝。无论如何,数据会在缓存中挂起一段时间。
对于对文件的随机访问(不重复读取同一个文件),filechannel是否更有效,因为mappedbytebuffer将占用它映射的内存,而filechannel不需要内存?
你的推理是错误的。无论使用哪种数据访问模式,filechannel都会执行额外的内存到内存复制,mappedbytebuffer则不会。
此外,内存映射本质上是惰性的。只有在访问相应的内存页时,才会从磁盘加载数据。
使用mappedbytebuffer和简单地将整个文件加载到内存中有什么区别?mappedbytebuffer的好处是它使用jvm堆外的内存,所以不涉及gc?
您可以在框中映射大于物理内存的文件数量级(单个mappedbytebuffer限制为2gib,因此需要多个映射)。通过映射访问文件数据的页面可以随时被操作系统收回。
就gc而言,mappedbytebuffer并不占用堆。
在filechannel和mappedbytebuffer之间选择什么?
使用内存映射数据还有其他令人讨厌的含义。
对内存中数据的任何访问都可能成为IO操作(如果未缓存内存页)。也就是说,每个bytebuffer.get()调用都可能被阻塞。
无法释放MappedByteBuffer。内存映射将保持活动状态,直到被gc清除。
这使得mappedbytebuffer成为一种罕见的访问数据的方式。
如果建议你避免使用Mappedbytebuffer
您的应用程序是交互式的,响应时间很重要。
您正在使用多个线程处理数据(IO上的单个线程可能会导致其他线程的级联阻塞)。
你想要非阻塞文件IO