Elasticsearch网站上的最新博客文章正在讨论其新的1.4 beta版本的功能。
我对它们如何利用文件系统缓存非常好奇:
最新版本增加了对文档值的支持。本质上,doc值提供的功能与内存中的字段数据相同,但是它们在索引时间写入磁盘。它们提供的好处是它们只占用很少的堆空间。从磁盘而不是从内存读取Doc值。尽管磁盘访问速度很慢,但是doc值受益于内核的文件系统缓存。与JVM堆不同,文件系统缓存不受32GB限制的约束。通过将字段数据从堆转移到文件系统缓存,可以使用较小的堆,这意味着可以更快地进行垃圾回收,从而获得更稳定的节点。 在此版本之前,doc值比内存中的现场数据要慢得多。 此版本中的更改显着提高了性能,使其几乎与内存中的字段数据一样快。
最新版本增加了对文档值的支持。本质上,doc值提供的功能与内存中的字段数据相同,但是它们在索引时间写入磁盘。它们提供的好处是它们只占用很少的堆空间。从磁盘而不是从内存读取Doc值。尽管磁盘访问速度很慢,但是doc值受益于内核的文件系统缓存。与JVM堆不同,文件系统缓存不受32GB限制的约束。通过将字段数据从堆转移到文件系统缓存,可以使用较小的堆,这意味着可以更快地进行垃圾回收,从而获得更稳定的节点。
在此版本之前,doc值比内存中的现场数据要慢得多。 此版本中的更改显着提高了性能,使其几乎与内存中的字段数据一样快。
这是否意味着我们可以操纵文件系统缓存的行为,而不是被动地等待来自操作系统的影响?如果是这样,我们如何在正常的应用程序开发中利用文件系统缓存?说,如果我正在编写Python或Java程序,该怎么做?
文件系统缓存是与OS内部工作相关的实现细节,对最终用户是透明的。不需要调整或更改。Lucene在管理索引段时已经使用了文件系统缓存。每次将某些文档索引到Lucene中(通过Elasticsearch)时,这些文档就会被写入段中,这些段首先被写入文件系统缓存中,然后经过一段时间(当translog(一种跟踪被索引文档的方式)被写入例如完整)将缓存的内容写入实际文件。但是,尽管要建立索引的文档位于文件系统缓存中,但仍可以访问它们。
doc值实现的这一改进指的是此功能现在可以使用文件系统缓存,因为它们是从磁盘读取,放入缓存并从那里访问的,而不是占用堆空间。
这篇出色的博客文章描述了如何访问此文件系统缓存:
在以前的方法中,我们依靠使用syscall在文件系统缓存和本地Java堆之间复制数据。如何直接访问文件系统缓存?这就是mmap所做的! 基本上,mmap就像将Lucene索引作为交换文件处理一样。mmap()syscall告诉操作系统内核将我们的整个索引文件虚拟地映射到先前描述的虚拟地址空间,并使它们看起来像我们的Lucene进程可用的RAM。然后,我们可以访问磁盘上的索引文件,就像它是一个大的byte []数组一样(在Java中,该文件由ByteBuffer接口封装以使其可以被Java代码安全使用)。如果我们从Lucene代码访问此虚拟地址空间,则无需进行任何系统调用,处理器的MMU和TLB将为我们处理所有映射。如果数据仅在磁盘上,则MMU将导致中断,并且O / S内核会将数据加载到文件系统缓存中。如果已在缓存中,则MMU / TLB会将其直接映射到文件系统缓存中的物理内存。
在以前的方法中,我们依靠使用syscall在文件系统缓存和本地Java堆之间复制数据。如何直接访问文件系统缓存?这就是mmap所做的!
基本上,mmap就像将Lucene索引作为交换文件处理一样。mmap()syscall告诉操作系统内核将我们的整个索引文件虚拟地映射到先前描述的虚拟地址空间,并使它们看起来像我们的Lucene进程可用的RAM。然后,我们可以访问磁盘上的索引文件,就像它是一个大的byte []数组一样(在Java中,该文件由ByteBuffer接口封装以使其可以被Java代码安全使用)。如果我们从Lucene代码访问此虚拟地址空间,则无需进行任何系统调用,处理器的MMU和TLB将为我们处理所有映射。如果数据仅在磁盘上,则MMU将导致中断,并且O / S内核会将数据加载到文件系统缓存中。如果已在缓存中,则MMU / TLB会将其直接映射到文件系统缓存中的物理内存。
与在Java程序中使用mmap的实际方法相关,我认为这是这样做的类和方法。