ripgrep 使用 -f/--file 从文件读取大量正则时变慢怎么调大 --dfa-size-limit 缓存
【免费下载链接】ripgrepripgrep recursively searches directories for a regex pattern while respecting your gitignore项目地址: https://gitcode.com/GitHub_Trending/ri/ripgrep
当你把正则集中放在一个文件里、用rg -f patterns.txt批量搜索时,ripgrep 会在模式文件变大的情况下明显变慢。这不是你的机器出了问题:FAQ 指出,模式文件过大时 ripgrep 的内部缓存(正则 DFA 缓存)可能装不下编译后的正则,于是回退到"更慢但更稳健"的正则引擎。对应的调优动作只有一个:用--dfa-size-limit把这个缓存的上限调大。本文按文档给出的路径讲清现象成因、改法、写法格式和验证方式。
先确认现象属于 -f/--file 模式文件过大的情况
-f/--file的行为见 flag 文档:从给定文件读取模式,每行一个模式;多次使用-f或与-e/--regexp混用时,所有模式都会被搜索;空行模式会匹配所有输入行,换行符不算模式的一部分;-f -表示从 stdin 读模式。一旦使用了-f或-e,其余位置参数一律被视为要搜索的文件或目录。
FAQ 对该场景的描述是:
If this pattern file gets too big, then it is possible ripgrep will slow down dramatically.Typicallythis is because an internal cache is too small, and will cause ripgrep to spill over to a slower but more robust regular expression engine.
也就是说,"变慢"本身只是征兆,文档的措辞是"通常是缓存太小"。判断依据就是你的使用方式符合上面这条链路:-f指向的模式文件规模明显增大后速度骤降。如果你的慢来自单个超长正则(比如 FAQ 里\pL{1000}这种),那对应的是另一个 flag--regex-size-limit,本文不展开。
主路径:给搜索命令加 --dfa-size-limit
直接在同一条命令上调大缓存上限,例如把上限设为 1GB:
rg -f patterns.txt --dfa-size-limit 1G .patterns.txt换成你自己的一行一个模式的文件;.换成要搜索的目录或文件。--dfa-size-limit的含义来自 flag 文档:"The upper size limit of the regex DFA"(正则 DFA 的上限大小)。文档同时说明默认上限对"单个模式或大量小模式"已经很宽裕,只有"very large regex inputs"才需要改,否则达到上限时会落入较慢的回退引擎——这正是-f大文件场景慢的机制。- 值的写法支持
K、M、G后缀,分别表示千字节、兆字节、吉字节;不带后缀则按字节数解析(同上 flag 文档)。 - 注意上限不等于内存占用:FAQ 明确说 "this doesn't mean ripgrep will use 1GB of memory automatically, but it will allow the regex engine to if it needs to"。这个值只是允许编译 DFA 时最多用到约这么多内存,实际用量取决于模式规模。
调大上限后,如果 FAQ 描述的场景成立("If this is indeed the problem, then it is possible to increase this cache and regain speed"),预期结果是速度恢复到正常水平。文档没有给出固定的耗时对照表,验证方式就是对比同一批模式和同一搜索目录下调参前后的搜索速度。
可选路径:写进 ripgrep 配置文件
如果这个调优要长期生效,可以放进配置文件而不是每次敲在命令上。GUIDE.md 的 Configuration file 一节 说明了规则:
- ripgrep 不会自动查找任何目录,必须设置环境变量
RIPGREP_CONFIG_PATH指向配置文件路径。 - 文件每行是一个 shell 参数(去掉首尾空白),
#开头是注释,没有转义机制。 - 带值的 flag 要么写成
--flag=value一行,要么 flag 一行、值一行;写成--flag value两行空格分隔的形式解析器无法识别。
按此规则,把下面一行写进你的配置文件即可:
--dfa-size-limit=1G配置文件的两个使用注意点(同样来自 GUIDE.md):
- 配置文件参数会被prepend到你命令行参数之前,所以命令行上再写
--dfa-size-limit 0之类的值会覆盖配置文件; - 想临时不加载配置文件时,加
--no-config即可。
验证配置是否真的被加载
用--debug确认 ripgrep 到底读了哪个配置文件、读到了哪些参数。GUIDE.md 明确推荐这个做法:
If you're confused about what configuration file ripgrep is reading arguments from, then running ripgrep with the
--debugflag should help clarify things. The debug output should note what config file is being loaded and the arguments that have been read from the configuration.
也就是说,跑一次rg --debug -f patterns.txt .,在 debug 输出里核对配置文件路径与--dfa-size-limit参数是否都出现了;出现即说明配置按预期生效。
另外,--dfa-size-limit的值解析是有边界的:flag 的解析测试 表明9G、9G、0、0K、0M、0G都能正确解析为对应字节数,而9999999999999999999999、9999999999999999G这类溢出值会直接报错退出。所以如果你填了一个极大的数,报错信息本身就是"值没生效"的信号,而不是静默失败。
限制与边界
- 这个 flag 只解决"模式文件多、大导致 DFA 编译超限、落入慢引擎"的问题。FAQ 对它的定性是 "This should only be changed on very large regex inputs",日常的小文件搜索不需要动它。
- 调大的只是上限,不是承诺分配:1GB 上限不代表 ripgrep 一定吃 1GB 内存。
- 单个超长正则编译超限是另一类问题,对应 FAQ 中的
--regex-size-limit(示例:rg '\pL{1000}' --regex-size-limit 1G),不要拿--dfa-size-limit去解。 - 变慢并不总是缓存问题,FAQ 用的是 "typically"。如果你加完
--dfa-size-limit仍然慢,说明根因不在这条链路上,需要另行排查,本文不覆盖其他慢的原因。
【免费下载链接】ripgrepripgrep recursively searches directories for a regex pattern while respecting your gitignore项目地址: https://gitcode.com/GitHub_Trending/ri/ripgrep
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考