菜单

性能

相关源文件

本页面概述了 ripgrep 的性能特点以及使其成为最快的 grep 类工具之一的技术。虽然基准测试涵盖了 ripgrep 的性能衡量方式,但本文档侧重于解释 ripgrep 之所以快速的原因及其实现的优化技术。

性能概览

Ripgrep 在保持正确性和灵活性的同时,专注于速度。其性能源于多层优化,从算法选择到底层代码优化。基准测试持续显示 ripgrep 在大多数场景下优于同类工具。

如 README 中所示,ripgrep 通常优于 The Silver Searcher (ag)、GNU grep、ugrep、ack 和 git grep 等工具,而且通常优势显著。这些性能优势在各种搜索模式和语料库类型中都得以保持。

关键性能特点

  • 对大型单个文件和目录遍历速度都很快
  • 针对面向行的搜索进行了优化
  • 完整的 Unicode 支持,性能损失极小
  • 有效的正则表达式编译和执行
  • 均衡的内存使用

性能架构

Ripgrep 的架构在每个层面都将性能作为关键考虑因素。

来源:README.md187-208 crates/regex/src/matcher.rs364-506

性能优化技巧

Ripgrep 的速度来自多种优化技术的协同作用

1. Rust 的 Regex 引擎优化

ripgrep 性能的基础是 Rust 的 regex crate,它提供了

  • 有限自动机:Regex 引擎使用有限自动机进行高效模式匹配
  • SIMD 优化:利用 CPU 矢量指令同时匹配多个字符
  • 字面量优化:识别必须存在于任何匹配中的字面量子字符串
  • UTF-8 感知:通过将 UTF-8 解码直接集成到匹配算法中,高效处理 Unicode

来源:README.md189-197 crates/regex/src/matcher.rs9-16

2. 内部字面量提取

Ripgrep 增强了 Regex 引擎的功能,并进行了额外的字面量提取

此优化从复杂模式中提取字面量字符串,并创建一个更简单的 Regex 来快速识别潜在匹配项。例如,对于类似 \w+foo\w+ 的模式,ripgrep 可以提取 foo,并用它在应用完整 Regex 模式之前查找候选行。

来源:crates/regex/src/literal.rs12-40 crates/regex/src/matcher.rs72-78

3. 战略性文件读取

Ripgrep 根据上下文选择最佳的文件读取策略

  • 内存映射,适用于大型单个文件
  • 增量缓冲区读取,适用于搜索多个文件或目录遍历

这种自动选择有助于在不同工作负载下保持高性能。

来源:README.md198-201

4. 非匹配字节检测

Ripgrep 分析模式以识别永不会出现在匹配中的字节

这允许在调用昂贵的 Regex 引擎之前,快速拒绝不可能匹配的文本区域。

来源:crates/regex/src/non_matching.rs9-81 crates/regex/src/matcher.rs480-486

5. 并行目录遍历

搜索目录时,ripgrep 使用并行处理

  • 无锁递归目录迭代器(通过 crossbeamignore crate)
  • 线程池,用于同时搜索多个文件
  • 自适应工作窃取,以平衡 CPU 核心之间的负载

来源:README.md205-208

6. 高效的忽略模式处理

Ripgrep 高效处理 .gitignore 和其他忽略模式

  • 使用 RegexSet 同时匹配文件路径和多个模式
  • 在流程早期应用忽略过滤器,避免不必要的工作

来源:README.md202-204

搜索过程优化流程

ripgrep 中的完整搜索过程结合了这些优化

这种多层方法确保 ripgrep 能够快速搜索各种类型的文件和目录结构,同时保持准确性。

来源:crates/regex/src/matcher.rs408-506 crates/regex/src/literal.rs44-124

按工作负载划分的性能特点

Ripgrep 的性能因搜索类型而异

工作负载性能特征备注
简单的字面量搜索极快利用 SIMD 优化
带字面量的正则表达式非常快使用内部字面量提取
复杂的正则表达式回退到优化的 Regex 引擎
大型单个文件良好高效使用内存映射
大量小文件优秀使用缓冲区读取进行并行处理
Unicode 内容良好内置 UTF-8 支持,开销极小

来源:README.md41-115

性能配置选项

用户可以通过命令行标志调整性能

标志性能影响
--mmap / --no-mmap强制/禁用内存映射策略
-j/--threads NUM控制并行搜索的线程数
--dfa-size-limit NUM设置 Regex DFA 的大小限制
-U/--multiline以牺牲性能为代价,实现多行匹配功能
-F/--fixed-strings通过将模式视为字面量字符串来提高性能
--regex-size-limit NUM设置编译后的 Regex 的最大大小

来源:crates/regex/src/config.rs45-68 crates/regex/src/matcher.rs199-229

调试性能问题

当 ripgrep 的性能不符合预期时,代码中包含诊断工具

  • Debug 级日志记录显示有关 Regex 编译和优化的详细信息
  • 错误处理提供有关大小限制和其他约束的有用消息

来源:crates/regex/src/error.rs1-94 crates/core/messages.rs1-139

实现细节

ripgrep 中的性能优化在几个关键组件中实现

  1. RegexMatcherBuilder:以性能为重配置 Regex 匹配
  2. InnerLiterals:提取和优化字面量以实现更快的搜索
  3. ConfiguredHIR:在保留优化机会的同时管理 Regex 配置
  4. ByteSet:跟踪永不会出现在匹配中的字节

广泛的基准测试套件(benchsuite)提供了与其他工具的持续性能测试,确保 ripgrep 保持其速度优势。

来源:crates/regex/src/matcher.rs14-362 crates/regex/src/literal.rs40-644 benchsuite/benchsuite1-3230

性能权衡

Ripgrep 做出了一些权衡以保持其速度

  • 默认针对面向行的搜索进行优化,而不是多行搜索
  • 某些正则表达式功能(如先行断言和反向引用)需要 PCRE2 模式,这可能会较慢
  • 与某些工具相比,内存使用量可能更高,以实现更快的搜索

来源:README.md116-158

通过结合这些技术,ripgrep 在保持准确性和可用性的同时,实现了卓越的搜索性能。