不要提前停止:以内存速度折叠源代码

无分支循环和字节空间算法如何让GitHub在单个内核上以> 45 GiB/s的速度将代码的每个字节折叠起来。不要提前停止:以内存速度折叠的源代码首先出现在GitHub博客上。

假设用户搜索咖啡馆,而您的语料库中包含咖啡馆,或者用户键入straße,而您存储了STRASSE。要使这些字符串算作匹配,您需要一个消除大小写差异的规范形式,以便两个仅在比较相同的情况下不同的字符串。

该表单是大小写折叠,它显示在文本匹配而不是显示的任何位置:搜索引擎、正则表达式(? i)标志、不区分大小写的用户名和主机名。这是一个基本的操作,但在GitHub,我们经常运行它。GitHub的代码搜索引擎Blackbird索引了超过1.8亿个存储库,超过480TB的源代码。

在我们提取ngram并构建索引之前,每个字节都是大小写折叠的,对于每个潜在的查询结果,都需要另一个(隐式或显式)大小写折叠操作来定位匹配项。在这个尺度上,即使是基本操作的速度也开始起作用。这篇文章是关于我们如何快速完成的,它从违反直觉的地方开始: ASCII快速路径中最大的胜利来自于删除优化,而不是添加优化。

事实证明,在没有分支的情况下扫描整个缓冲区比在第一个非ASCII字节处提前停止更快。我们将结果开源为名为casefold的Rust crate。

折叠不是小写字母很容易达到str:: to_lowercase,但小写字母和折叠是不同的操作,具有不同的目标:小写字母用于显示,并且与区域和上下文相关:希腊语最后的sigma小写字母在单词末尾为ς, σ在其他地方,土耳其语I小写字母与英语I不同。