Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/371.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 为什么mmap()(内存映射文件)比read()快_Java_C_Linux_Io_Operating System - Fatal编程技术网

Java 为什么mmap()(内存映射文件)比read()快

Java 为什么mmap()(内存映射文件)比read()快,java,c,linux,io,operating-system,Java,C,Linux,Io,Operating System,最近,我正在研究Java NIO的MappedByteBuffer。 我读过一些关于它的帖子,它们都提到“mmap()比read()快。” 我的结论是: 我处理MappedByteBuffer==内存映射文件==mmap() read()必须通过磁盘文件->内核->应用程序读取数据,因此它具有上下文切换和缓冲区复制功能 他们都说mmap()的复制或系统调用比read()少,但我知道它还需要在您第一次访问文件数据时从磁盘文件中读取。所以它第一次读到:虚拟地址->内存->页面错误->磁盘文件->内核

最近,我正在研究Java NIO的MappedByteBuffer。 我读过一些关于它的帖子,它们都提到“mmap()比read()快。”

我的结论是:

  • 我处理MappedByteBuffer==内存映射文件==mmap()

  • read()必须通过磁盘文件->内核->应用程序读取数据,因此它具有上下文切换和缓冲区复制功能

  • 他们都说mmap()的复制或系统调用比read()少,但我知道它还需要在您第一次访问文件数据时从磁盘文件中读取。所以它第一次读到:虚拟地址->内存->页面错误->磁盘文件->内核->内存。除了可以随机访问之外,最后3个步骤(磁盘文件->内核->内存)与read()完全相同,那么mmap()的复制或系统调用如何比read()少呢

  • mmap()和swap file之间的关系是什么,操作系统会将内存中使用最少的文件数据放入swap(LRU)?所以,当您第二次访问这些数据时,操作系统从交换文件而不是磁盘文件中检索它们(无需复制到内核缓冲区),这就是为什么mmap()的复制和系统调用更少的原因

  • 在java中,MappedByteBuffer是在堆外分配的(它是一个直接缓冲区)。那么,当您从MappedByteBuffer读取时,是否意味着它需要从java堆外部向java堆中多复制一个内存


  • 有人能回答我的问题吗?谢谢:)

    你在比较苹果和桔子
    mmap()
    read()
    快,因为它不做任何I/O。I/O延迟到您访问映射产生的内存地址时。该I/O与
    read(),
    非常相似,并且该I/O是否比
    read()
    快是一个非常没有意义的问题。在我接受之前,我希望看到一个合适的基准

    我处理
    MappedByteBuffer
    ==内存映射文件==
    mmap()

    read()
    必须通过磁盘文件->内核->应用程序读取数据,因此它有两次上下文切换和缓冲区复制

    和什么相比

    他们都说mmap()的复制或系统调用比
    read(),

    它的系统调用更少。它是否具有较少的复制取决于实现。当然,通过DMA直接读取和写入数据是可能的,但具体操作系统是否这样做取决于具体操作系统

    但据我所知,它还需要在您第一次访问文件数据时从磁盘文件中读取数据

    所以它第一次读到:虚拟地址->内存->页面错误->磁盘文件->内核->内存。除了可以随机访问之外,最后3个步骤(磁盘文件->内核->内存)与read()完全相同,那么mmap()的复制或系统调用如何比read()少呢

    因为DMA,如果实现的话

    mmap()和交换文件之间的关系是什么

    分配给映射的内存是进程地址空间的一部分,它是虚拟的,需要交换,交换文件中必须有空间容纳它,就像其他内存一样

    操作系统是否会将内存中使用最少的文件数据放入交换(LRU)

    没有

    所以,当您第二次访问这些数据时,操作系统从交换文件而不是磁盘文件中检索它们(无需复制到内核缓冲区),这就是为什么mmap()的复制和系统调用更少的原因

    不,那样做是完全错误的

    在java中,
    MappedByteBuffer
    从堆中分配(它是一个直接缓冲区)

    那没有道理。直接缓冲区不是从堆中分配出来的,它们是由
    mmap()
    或任何平台API分配的,作为新内存。不在堆里。正确的说法是,
    MappedByteBuffer
    是直接缓冲区

    那么,当您从MappedByteBuffer读取时,是否意味着它需要从java堆外部向java堆中多复制一个内存


    是的,但不是因为上述原因。原因是您必须调用
    MappedByteBuffer.get()/put(),
    ,这本身就是一个额外的步骤。

    1:是的,这本质上就是MappedByteBuffer

    2:“磁盘文件->内核”不一定涉及复制

    3:使用内存映射文件,一旦内核将文件读入其缓存,它就可以简单地将缓存的该部分映射到进程中,而不必将数据从缓存复制到进程指定的位置

    4:如果内核决定从内存映射文件中交换一个页面,它将不会将该页面写入该页面文件;在丢弃页面之前,它会将页面写入原始文件(它的映射源文件)。将其写入页面文件是不必要的,并且会浪费页面文件空间


    5:是的。例如,如果调用
    get(byte[])
    ,则数据将从堆外映射复制到数组中。请注意,诸如
    get(byte[])
    之类的函数需要为任何类型的缓冲区复制数据-这并不特定于内存映射文件。

    对于第4部分,操作系统磁盘缓存似乎也考虑到了这一点。除了使用模式带来的最终性能好处外,内存映射文件在某种程度上比堆缓冲区更适合共享机器。当操作系统需要回收物理内存时,可以保存和取消映射内存映射文件,当程序再次访问它们时,可以透明地重新映射。我不会称之为“比较苹果和桔子”。这两种机制共享读取和写入文件的目的。听起来很像。@zneak Comparing
    mmap()
    read()。事实上,OP似乎在质疑这一说法。我认为他对使用
    mmap
    读取与您相同的数据的全球性能更感兴趣