当前位置: 首页 > news >正文

【lucene】MMapDirectory 在FSDirectory基础上干了啥?

一句话:  
**MMapDirectory 只是把 “读写文件” 从普通的 FileChannel I/O 换成了 mmap(内存映射),其余所有逻辑(文件创建、删除、锁、pending_segments 处理等)都和 FSDirectory 共用同一套代码**。

---

### 1. FSDirectory 已经做了什么  
FSDirectory 提供了:  
- 创建/打开/删除文件的统一实现(createOutput / openInput / deleteFile)  
- 对 pendingDeletes、文件锁、临时文件的处理  
- 可插拔的 `FSIndexOutput`/`FSIndexInput` 实现(用 `FileChannel.read/write` 做真正的 I/O)  

---

### 2. MMapDirectory 只改了 I/O 实现  
```java
public final class MMapDirectory extends FSDirectory {
...
@Override
public IndexInput openInput(String name, IOContext context) throws IOException {
ensureOpen();
Path path = directory.resolve(name);
// 用 mmap 而不是 FileChannel.read
return new MMapIndexInput(name, path, chunkSizePower, preload, useUnmapHack);
}

    /* IndexOutput 仍然是 FSIndexOutput(FileChannel.write),
因为 mmap 写文件需要 RandomAccessFile + rw,且性能不一定更好,
Lucene 只在“读”路径用 mmap,“写”路径保留 FileChannel。 */
}
```

- **读文件** → `MMapIndexInput`:把文件映射到 `MappedByteBuffer`,后续读操作就是内存访问。  
- **写文件** → 仍用 `FSIndexOutput`(FileChannel.write),因为:  
- mmap 写需要 `RandomAccessFile` + `MapMode.READ_WRITE`,且每次扩展文件长度要重新映射,成本高;  
- 写通常是顺序大块写入,FileChannel 反而更快。  

---

### 3. 额外提供的调优参数  
MMapDirectory 额外暴露:  
- `setPreload(true)`:在 map 后立即 `madvise(MADV_WILLNEED)`,减少首次访问缺页。  
- `setUseUnmapHack(true)`:用 Cleaner 或 Unsafe 手动 `unmap`,避免 64-bit JVM 下映射残留导致 “无法删除文件” 的问题(Windows 上尤其重要)。  

---

### 总结对比

| 维度            | FSDirectory 默认实现 | MMapDirectory                      |
|-----------------|----------------------|------------------------------------|
| Directory 框架  | ✅ 同一套             | ✅ 继承 FSDirectory                |
| 读文件          | FileChannel.read     | mmap(MappedByteBuffer)          |
| 写文件          | FileChannel.write    | 同 FSDirectory(未用 mmap)       |
| 额外调优        | 无                   | preload、unmapHack、chunkSizePower |
| 适用场景        | 通用                 | 读多写少,64-bit、大索引、随机查  |

因此:**MMapDirectory = FSDirectory + 读路径换成 mmap,其余完全复用**。

对,**在 open reader 的环节差异最大**:

1. 当你调用  
`DirectoryReader.open(directory)` 或 `IndexReader.open(...)`  
最终都会走到 `SegmentCoreReaders` → `openInput(name, IOContext.READONCE / RANDOM / MERGE)` 去为每个段文件(`.cfs`, `.fdx`, `.tim`, `.doc`, …)创建 `IndexInput`。

2. 如果目录是:
- **FSDirectory** → 返回 `FSIndexInput`,底层是 `FileChannel.read`  
- **MMapDirectory** → 返回 `MMapIndexInput`,底层是 `MappedByteBuffer`(mmap)

3. **差异只在读阶段**  
- 写文件时两者都走 `FSIndexOutput`(FileChannel.write),没有 mmap。  
- 因此只有 **reader 打开后** 的随机访问、倒排表遍历、跳表查询等读操作,才会体验到 mmap 带来的:
- 地址空间直接映射,减少一次内核→用户空间拷贝  
- 大文件分段映射,降低 GC 压力  
- 预读/缓存效果由 OS 页缓存自动完成

4. **对上层 API 没区别**  
上层代码(`IndexSearcher.search`, `TermsEnum`, `StoredFields`…)感知不到,只是底层 `IndexInput` 实现不同。

一句话:**writer 阶段无差异;reader 阶段因 mmap 而提速,尤其随机读多的查询**。

http://www.lryc.cn/news/601236.html

相关文章:

  • 【NLP舆情分析】基于python微博舆情分析可视化系统(flask+pandas+echarts) 视频教程 - 微博舆情分析实现
  • AI驱动的金融推理:Fin-R1模型如何重塑行业决策逻辑
  • listen() 函数详解
  • GPGPU基本概念
  • 深入解析 Vue 3 中 v-model 与表单元素的绑定机制
  • 北京-4年功能测试2年空窗-报培训班学测开-第六十一天-模拟面试第一次
  • 五自由度磁悬浮轴承转子不平衡振动破壁战:全息前馈控制实战密码
  • 结构化文本文档的内容抽取与版本重构策略
  • 程序代码篇---python获取http界面上按钮或者数据输入
  • LeetCode 611.有效三角形的个数
  • 机器学习项目一基于KNN算法的手写数字识别
  • 设计模式(十二)结构型:享元模式详解
  • AI Coding IDE 介绍:Cursor 的入门指南
  • 设计模式(八)结构型:桥接模式详解
  • 以太坊ETF流入量超越比特币 XBIT分析买币市场动态与最新价格
  • 分类预测 | MATLAB基于四种先进的优化策略改进蜣螂优化算法(IDBO)的SVM多分类预测
  • 机器学习—线性回归
  • 数学基础薄弱者的大数据技术学习路径指南
  • Java Ai (day01)
  • Oracle EBS 库存期间关闭状态“已关闭未汇总”处理
  • 【网络协议安全】任务15:DHCP与FTP服务全配置
  • docker与k8s的容器数据卷
  • S7-1500 与 S7-1200 存储区域保持性设置特点详解
  • 三、搭建springCloudAlibaba2021.1版本分布式微服务-springcloud loadbalancer负载均衡
  • Java 大视界 -- Java 大数据机器学习模型在电商客户细分与精准营销活动策划中的应用(367)
  • 机械学习----knn实战案例----手写数字图像识别
  • 人工智能开发框架 04.网络构建
  • spring gateway 配置http和websocket路由转发规则
  • Linux驱动21 --- FFMPEG 音频 API
  • Spring Boot + @RefreshScope:动态刷新配置的终极指南