将文件用于共享内存IPC

问题描述 投票:0回答:2

在我的应用程序中,有一个过程将数据写入文件,然后响应于接收到请求,将通过网络将(某些)该数据发送到请求过程。这个问题的基础是看两个进程碰巧在同一主机上时,是否可以加快通信速度。 (就我而言,进程是Java,但是我认为此讨论可以更广泛地应用。)

[这里有一些项目使用Java的FileChannel.map()返回的MappedByteBuffers作为在同一主机上的JVM之间共享内存IPC的一种方式(请参阅Chronicle Queue,Aeron IPC等。)>

加快同主机通信的一种方法是,让我的应用程序使用其中一种技术,为同主机通信提供请求-响应路径,或者结合现有的写入数据文件的机制,或者通过提供一种统一的通信和写入文件的方式。

另一种方法是允许请求过程直接访问数据文件。

[我倾向于第二种方法-假设它是正确的-因为它更容易实现,并且比为每个请求复制/传输数据副本更有效(假设我们没有替换现有的机制,用于写入文件)。

本质上,我想了解当两个进程可以访问同一个文件并使用它进行通信时,确切地说会发生什么,特别是Java(1.8)和Linux(3.10)。

根据我的理解,如果两个进程同时打开相同的文件,则它们之间的“通信”本质上将是通过“共享内存”。

[请注意,这个问题与是否使用MappedByteBuffer无关,它与性能的影响无关—与映射文件读写相比,使用映射的缓冲区以及减少复制和系统调用的可能性很可能降低,但这可能需要对应用程序进行重大更改。

这是我的理解:

  1. Linux从磁盘加载文件时,它将文件的内容复制到内存中的页面。该内存区域称为页面缓存。据我所知,无论使用哪种Java方法(FileInputStream.read(),RandomAccessFile.read(),FileChannel.read(),FileChannel.map())或本机方法来读取文件(被“免费”删除并监视“缓存”值)。
  2. [如果另一个进程尝试加载同一文件(尽管它仍驻留在缓存中),则内核会检测到该文件,不需要重新加载该文件。如果页面缓存已满,则页面将被逐出-脏的页面将写回到磁盘中。 (如果显式刷新磁盘并定期使用内核线程刷新,则页面也会被写回)。
  3. [在缓存中已经有一个(大)文件大大提高了性能,远远超过了我们用来打开/读取该文件的Java方法所基于的差异。
  4. 如果使用mmap系统调用(C)或通过FileChannel.map()(Java)加载文件,则基本上将文件的页面(在高速缓存中)直接加载到进程的地址空间中。使用其他方法打开文件,该文件被加载到不在进程地址空间中的页面中,然后各种读取/写入该文件的方法将这些页面的某些字节/从这些页面复制到进程地址空间中的缓冲区中。 。避免该复制具有明显的性能优势,但我的问题与性能无关。
  5. 因此,总的来说,如果我理解正确,虽然映射提供了性能上的优势,但它似乎并没有提供我们不能仅仅从Linux和页面缓存的性质中获得的任何“共享内存”功能。 。

所以,请让我知道我的理解力在哪里。

谢谢。

在我的应用程序中,有一个过程将数据写入文件,然后响应于接收到请求,将通过网络将(某些)该数据发送到请求过程。基础...

java linux ipc memory-mapped-files mappedbytebuffer
2个回答
0
投票

值得一提的三点是:性能,并发更改和内存利用率。


0
投票

我的问题是,在Java(1.8)和Linux(3.10)上,对实现共享内存IPC确实需要MappedByteBuffers,还是对公共文件的任何访问都可以提供相同的功能?

© www.soinside.com 2019 - 2024. All rights reserved.