代码之家  ›  专栏  ›  技术社区  ›  Alexis

FileChannel与MappedByteBuffer在随机访问中的比较?

  •  1
  • Alexis  · 技术社区  · 8 年前

    据我所知,MappedByteBuffer有几个好处,例如:

    1. 它将用户空间内存地址映射到内核空间内存地址,从而避免在读取文件时将内存从内核空间复制到用户空间

    2. 在第一次读取文件中的一个片段(等缓冲区中从0到100的偏移量)后,该片段将被缓存在内存中,因此当您第二次从缓冲区读取同一片段时,您将直接从内存中读取,而不是从磁盘中读取。

    我的问题是:

    1. 我的上述理解是否正确?

    2. 如果我的理解是正确的,那么当你只读一次这篇文章时(不要再读了,这样它就不会从内存中读取),使用FileChannel也是一样的吗。读取(缓冲区,位置)并使用MappedByteBuffer。获取(字节[],偏移量,长度)?

    3. 对于随机访问文件(不重复读取同一段),FileChannel是否会更有效,因为MappedByteBuffer会占用它映射的内存,而FileChannel不需要内存?

    4. 我使用MappedByteBuffer和将整个文件加载到内存中有什么区别。MappedByteBuffer的好处是它使用JVM堆之外的内存,所以不需要GC?

    1 回复  |  直到 8 年前
        1
  •  3
  •   Community Mohan Dere    6 年前

    让我逐一回答你的问题。

    据我所知,MappedByteBuffer有几个好处,例如:

    1. 它将用户空间内存地址映射到内核空间内存地址,从而避免在读取文件时将内存从内核空间复制到用户空间

    2. 在第一次读取文件中的一个片段(等缓冲区中从0到100的偏移量)后,该片段将被缓存在内存中,因此当您第二次从缓冲区读取同一片段时,您将直接从内存中读取,而不是从磁盘中读取。

    你的陈述不是无效的。 尽管如此,重要的是不要错过简单的事实。文件数据的访问总是涉及缓存( except when it does not )。如果缓存中的内存映射页映射到您的地址空间,则会涉及FileChannel额外内存拷贝。

    如果我的理解是正确的,那么当你只读一次这篇文章时(不要再读了,这样它就不会从内存中读取),使用FileChannel也是一样的吗。读取(缓冲区,位置)并使用MappedByteBuffer。获取(字节[],偏移量,长度)?

    否,FileChannel。读取(缓冲区、位置)涉及额外的内存拷贝。无论如何,数据将在缓存中保留一段时间。

    对于随机访问文件(不重复读取同一段),FileChannel是否会更有效,因为MappedByteBuffer会占用它映射的内存,而FileChannel不需要内存?

    你的推理是错误的。对于任何一种数据访问模式,FileChannel都会进行额外的内存到内存拷贝,而MappedByteBuffer则不会。 此外,内存映射本质上是懒惰的。只有在访问相应的内存页时,才从磁盘加载数据。

    我使用MappedByteBuffer和将整个文件加载到内存中有什么区别。MappedByteBuffer的好处是它使用JVM堆之外的内存,所以不需要GC?

    您可以将比物理内存大几个数量级的文件映射到机箱上(单个MappedByteBuffer限制为2GiB,因此需要多个映射)。通过映射访问文件数据的页面可以随时被操作系统收回。 实际上,就GC而言,MappedByteBuffer并不占用堆。

    在FileChannel和MappedByteBuffer之间选择什么?

    使用内存映射数据还有其他令人讨厌的含义。

    1. 对内存中数据的任何访问都可能成为IO操作(如果内存页未缓存)。一、 e.每一个ByteBuffer。get()调用可能被阻塞。
    2. 无法处置MappedByteBuffer。在GC清理之前,内存映射将保持活动状态。

    这使得MappedByteBuffer成为一种奇特的、很少使用的数据访问方式。

    如果我建议你 避免 MappedByteBuffer如果

    1. 您的应用程序是交互式的,响应时间很重要。
    2. 您正在积极使用多个线程来处理数据(IO上的单个线程可能会导致其他线程的级联阻塞)。
    3. 您需要非阻塞文件IO