高速正規表現検索:エージェントツール用テキストインデックス化

2026/03/24 15:31

高速正規表現検索:エージェントツール用テキストインデックス化

RSS: https://news.ycombinator.com/rss

要約

Japanese Translation:

この記事は、現代のAI支援型コーディングツールがまだgrepスタイルの正規表現検索に依存していると主張しています。しかし、クラシックユーティリティであるgrepや、より高速なripgrepさえも、大規模なモノレポでは実用的ではありません。なぜなら、毎回すべてのファイルをスキャンしなければならないからです。そのため、効率的な検索にはローカルに構築された専用インデックスが必要です。初期研究では、正規表現検索にはインデックスが不可欠であることが示され、トリグラムやサフィックス配列といった代表的なアプローチがあり、それぞれにトレードオフがあります(トリグラムインデックスは大きなポスティングリストを生成し、サフィックス配列は高価な再構築を必要とします)。新しい確率的トリグラムや疎n-gram手法は、クエリ速度を保ちつつインデックスサイズを削減します。実験では、ローカルクライアント側の正規表現インデックスがComposer 2などのモデルに対して数秒からほぼリアルタイムへと遅延を短縮することが示されました。本提案のアーキテクチャは、ポスティングリストをハッシュ–オフセットテーブル付きでファイルに保存し、バイナリ検索を高速化するためにメモリマップしてローカルにインデックスを構築します。これによりネットワーク往復が不要になり、ローカル編集後もインデックスは新鮮な状態を保ちます。実証結果は、大規模企業レポジトリでの遅延削減が顕著であり、デバッグやリファクタリング作業を高速化することを示しています。このシフトは、ツールエコシステム内でローカルインデックスベースの検索エンジンへの広範な移行を示しており、開発者と企業に生産性向上という形で恩恵をもたらします。

本文

時間は平坦な円です。
1973年に最初の grep がリリースされたとき、それはファイルシステム上のテキストファイルに対して正規表現を照合するだけの基本的なユーティリティでした。年月が経つにつれ、開発ツールが高度化するとともに、次第により専門的なツールへと置き換えられていきました。まずは ctags のような概略的構文インデックス、その後多くの開発者がコードベースを効率よくナビゲートできる IDE に移行し、解析や構文インデックス作成に加えて型情報を補完するものへと進化しました。

最終的には Language Server Protocol (LSP) が標準化され、古いものも新しいテキストエディタすべてがこれらのインデックスを利用できるようになりました。そして LSP が標準となりつつあるその頃に Agentic コーディングが登場し、何と聞いてください――エージェントは grep を使うことが大好きなのです。


問題点

コンテキストを収集するための最先端技術はいくつかあります。過去に、セマンティックインデックスを多くのタスクで利用すればエージェント性能は大幅に向上すると話し合ったことがありますが、モデル自身が正規表現検索でしか解決できない特定のクエリも存在します。つまり 1973 年に戻る必要があります――それでも分野は少し進歩しています。

ほとんどのエージェントハーネス(私たちものを含め)は、検索ツールとして ripgrep をデフォルトで使用します。Andrew Gallant が開発したスタンドアロン実行ファイルで、古典的な grep の代替としてより合理的なデフォルト(例えば無視するファイルの扱い)と圧倒的に高速なパフォーマンスを提供します。ripgrep は正規表現マッチング時に速度を重視して設計されたため、非常に速いという評判があります。

しかし、どれだけ高速であっても ripgrep にはひとつの重大な制限があります ― すべてのファイルの内容を対象にマッチする 必要がある点です。小規模プロジェクトなら問題ありませんが、Cursor のユーザー(特に大規模エンタープライズ顧客)の多くは非常に大きなモノレポで作業しています。そのため rg コマンドの実行時間が 15 秒を超えるケースが日常茶飯事であり、コードを書いている最中にエージェントと対話しながら進めるワークフローを著しく遅延させます。

正規表現検索は Agentic 開発の重要な要素であり、その対象を明示的に扱うことが不可欠です。従来の IDE が Go To Definition のような操作のためにローカル構文インデックスを作成するのと同様に、我々はエージェントがテキスト検索を行う際に使用するコアオペレーション用のインデックスを構築しています。


典型的なアルゴリズム

テキストデータをインデックス化して正規表現マッチングを高速化するアイデアは古くから存在します。1993 年に Zobel、Moffat、Sacks‑Davis が発表した論文 Searching Large Lexicons for Partially Specified Terms using Compressed Inverted Files で、n-gram(文字列の幅が n のセグメント)を使った逆インデックスと正規表現を n‑gram の木構造に分解して検索する手法が紹介されました。

この概念は、その論文よりも 2012 年に Russ Cox が Google Code Search 停止直後に書いたブログ投稿で広く知られるようになりました。ここでは、これらのインデックスに共通する基本構成要素を簡潔に復習します。

逆インデックス

検索エンジンの根幹となるデータ構造です。対象文書集合から各文書を トークン に分割(tokenization)し、各トークンをキーとして辞書型構造に格納します。値はそのトークンが出現するすべての文書リスト(posting list)です。検索時にはトークンごとに posting list をロードし、交差させることですべてのトークンを含む文書を取得します。

正規表現で機能しない理由
ソースコードは自然言語ではなく、単語単位で分割すると識別子が誤って切断され、文字レベルでの精度が必要になるケースが多いです。プログラミング言語ごとの構文を尊重したトークナイズ手法が求められます。

3-gram 分解(Trigram)

ソースコードに対する単純なトークン化は正規表現検索には不適切です。そこで典型的なアルゴリズムでは trigram(重複しながら 3 文字ずつ切り出す)を採用します。

  • バイグラムだとキー数が少なく、posting list が膨大になり効率が落ちます。
  • クワッドグラムだと posting list は小さくなるものの、インデックス全体で数十億ものキーが必要になり管理が難しくなります。

3 文字はトークン化を簡潔に保ちながら、インデックスサイズを実用的に抑えるバランス点です。正規表現自体の解析も必要ですが、リテラル文字列や選択肢、文字クラスから trigrams を抽出し、適宜 union(OR)または intersection(AND)で posting list を結合します。

全体像

  1. インデックス構築 – 各文書のすべての重複 3-gram を抽出し、そのオフセットを posting list に追加。
  2. クエリ時 – 正規表現を trigrams の集合に分解、対応する posting list をロードして交差/結合し候補文書集合を取得。
  3. 検証 – 候補文書ごとに本物の正規表現を実行。これは全コードベースを走査するよりはるかに低コストです。

google/codesearch や sourcegraph/zoekt などがこの trigrams ベースの逆インデックスで大規模な検索性能を実現していますが、以下の課題があります。

  • インデックスサイズが大きい場合もある。
  • クエリ時のヒューリスティック(trigram 数の選択)が重要:少ないと候補が多すぎ、逆に多いと posting list の読み込みコストが増える。

Suffix Array – 逸話

テキスト検索アルゴリズム史を語る際には、Nelson Elhage が 2015 年に開発した livegrep の実装も触れておく価値があります。大規模プロジェクトと比べて livegrep は極めて小さく、Linux カーネルの最新バージョンのみをインデックス化していますが、そのスコープの狭さゆえに実装は独特です。

Suffix Array は文字列のすべての接尾辞をソートした配列です。大規模なコーパスではスペースコストが高いですが、元の文字列へのアクセスが可能ならば各接尾辞オフセットだけを格納して圧縮できます。

  1. 正規表現をリテラルに分解。
  2. 各リテラルで suffix array を二分探索し、潜在的マッチ位置を取得。
  3. [a‑z]
    のような文字範囲は、開始と終了の境界を二分探索して求めます。

欠点としては、すべての文書を 1 つの文字列に結合しなければならないため更新が難しいこと、マッチ位置を元ファイルへ戻す処理が煩雑になる点があります。


Probabilistic Trigram Masks(Bloom フィルタ)

GitHub の Project Blackbird は、trigram インデックスに「次の文字」情報を追加する手法を検証しました。直接四文字目を格納すると quadgram インデックスになってしまうため、Bloom フィルタ(8 ビット)で可能なすべての続き文字を保持します。

  • locMask – 位置を 8 で割った余りを示す 8‑bit マスク。
  • nextMask – 次に来る文字の Bloom フィルタ(8 ビット)。

この方式は quadgram をクエリできつつインデックスサイズを抑え、隣接 trigrams が連続していることも確認できます。しかし Bloom フィルタが飽和すると選択性が低下し、誤検知が増えるという欠点があります。


Sparse N‑grams

ClickHouse の正規表現演算子や GitHub の新しい Code Search で採用されているのが Sparse N‑grams です。すべての連続 n-gram を抽出する代わりに、文字ペアごとに決定的な重み(例:CRC32 ハッシュ)を付与し、境界の重みが内部よりも高い部分だけを抜き取ります。

  1. 文字対ごとに重み計算。
  2. 内部のすべてのペアより大きい境界のみを抽出。
  3. 抽出された n-gram は可変長で、従来の trigram よりはずっと少数です。

重み付けに頻度情報(稀な文字対に高い値)を加えると、さらに n‑gram の数を減らせます。この手法はクエリ時に最小カバー集合を再構築できるため、高速で特異性の高い検索が可能です。


クライアント側インデックス

上記の設計は従来サーバーサイドで実装されてきましたが、Agentic 開発では ローカル で構築・照合する方針が適しています。

  • インデックスは候補セットのみを提供し、各ファイルはやはりローカルで走査します。
  • クライアントに保持すればネットワーク遅延がなくなり、レイテンシが向上します。
  • Git コミットと連動させることで、インデックスを差分レイヤーとして高速更新可能です。

実装のポイント:

  1. Posting File – すべての posting list を連続したバイナリファイルに格納。
  2. Lookup Table – n‑gram のハッシュと Posting File 内オフセットをソートして保持し、
    mmap
    で高速検索。
  3. ハッシュのみで管理するため、衝突は極めて稀で偽陰性が生じません。

このレイアウトによりメモリ使用量を最小限に抑えつつ、クエリ性能を最大化できます。


結論

高速モデル(例:Composer 2)へテキスト検索インデックスを提供することで、Agentic ワークフローの質が飛躍的に向上します。特に大規模 Enterprise リポジトリでは grep の遅延がコードサイズと比例して増大するため、全コードベースを走査する時間を削減できれば、バグ調査時や再帰的な修正作業で顕著な時間短縮につながります。

今後は既存のアプローチ(セマンティックインデックス、確率的トリグラムマスク、Sparse N‑gram)を最適化しつつ、世界最大規模のリポジトリでさらにパフォーマンス向上を実現する新しい手法を探求していきます。

同じ日のほかのニュース

一覧に戻る →

2026/03/27 5:53

**Deploytarot.com – デプロイメントのタロットカードリーディング** 「デプロイプロジェクトに対する洞察に満ちた指針を、個別化されたタロットカードリーディングで得ましょう。」

## 日本語訳: 記事では、ソフトウェアデリバリーを一連のタスク、リスク、およびステークホルダーの視点として可視化する比喩的な「カードデッキ」を紹介しています。各カードは、A/Bテスト、AI統合、DB移行、サーバーレス移行などの特定のタスクとアイコンおよび簡潔な説明をペアにします。リスクカードでは、「どの指標が重要かについてゼロコンセンサス」や「カードが見ている」という不確実性を列挙しています。役割カードは、CEO、CISO、CTO、清掃係、クライアント、コンサルタント、請負業者、DBA、データサイエンティスト、デザイナー、DevOpsエンジニア、エンジニアリングマネージャー、人事、インターン、ジュニア開発者、オフショア開発者、プロダクトマネージャー、プロジェクトマネージャー、QAエンジニア、受付係、営業、スクラムマスター、セキュリティエンジニア、シニアデベロッパー、SRE、ステークホルダー、テックリード、VP of Engineering など多岐にわたるステークホルダーの各役割がデプロイメント決定をどのように見ているかを示す一文の逸話を提供します。 物語は「アーケナはあなたのスプリント速度を気にしない」と強調し、代わりに「時折その終点で崖がある」という潜在的な落とし穴をハイライトすることに焦点を当てています。 デッキは各引きごとに新たにシャッフルされますが、「戻ってくると覚えている」と説明され、過去の洞察を保持する動的システムであることを示唆しています。 速度よりもリスク認識を前面に押し出すことで、このモデルは多様な役割間で明確なコミュニケーションと整合性を維持し、よりレジリエントなデリバリープロセスを育むことを奨励します。

2026/03/26 0:46

**2025年に多くの制御室がシー・フロムグリーン(海泡色)を採用した理由は?** | 要因 | なぜ重要だったか | |------|-----------------| | **エルゴノミクス研究** | その年に公開された調査では、海泡色が目の疲労を軽減し、長時間の監視作業中に集中力を向上させることが示されました。 | | **省エネルギー動向** | この色は白や黄よりも自然光を反射しやすく、24時間稼働する環境で人工照明の必要性を低減します。 | | **ブランドアイデンティティ** | いくつかのテック大手が「グリーンファースト」サステナビリティイニシアチブを開始し、その理念に合わせて制御室も再設計されました。 | | **心理的影響** | 緑は落ち着きとバランスに結びついており、オペレーターが重要なシステムを管理する際には不可欠な特性です。 | | **規制ガイドライン** | 新たな安全基準では、状態インジケータの可視性を高めるカラースキームが推奨されており、海泡色は赤警報と衝突せずにその要件を満たしました。 | まとめると、エルゴノミクス科学、省エネルギー政策、企業ブランディング、心理研究、そして更新された規制の融合が、2025年の制御室にとって実用的でストレスの少ない選択肢として海泡色を押し上げました。

## Japanese Translation: 記事は、核施設や工業サイトでよく見られる特徴的な海藻緑色を第二次世界大戦時のファーバー・ビレン(Faber Birren)の産業用カラー安全コードに遡ります。2017年夏、著者はオークリッジのX‑10グラファイト炉(「ファットマン」研究のためにロスアラモスへ輸送されたプルトニウムを生成した24フィート四方のブロック)を訪れ、壁と制御パネルでビレンが推奨するライト/ミディアムグリーンが一貫して使用されていることに注目しました。ビレン(1919–1996)は1944年に国立安全協議会によって承認されたカラーコードを開発し、1948年までに世界中で採用されました。このコードは次のような色から構成されています: - **Fire Red** – 火災防止、緊急停止、可燃液 - **Solar Yellow** – 注意、物理的危険 - **Alert Orange** – 危険機械部品 - **Safety Green** – 救急装置、出口、洗眼ステーション - **Caution Blue** – 非安全通知または故障表示 - **Light Green** – 視覚疲労を軽減する壁色 同じスキームがハンフォードのB‑レイザー制御室にも見られます:下部壁にミディアムグリーン、機械にはミディアムグレー、火災防止にファイヤーレッド、低照度エリアにベージュ、床はライトです。ビレンは、このような機能的カラー使用が明るさを制御し、事故を減らし、メンテナンス基準を向上させ、労働士気を高めると主張しました。 ドイツの「ケルン橋緑(Cologne Bridge Green)」は、橋という工業用途で開発された海藻緑色の別例です。著者はまた、古い自動車部品リストに触発されて「Parts List」というフォントをデザインし、オイル交換待合室の雰囲気を呼び起こすことを目的としています。このフォントは彼女のウェブサイトで入手可能です。彼女はこれら歴史的安全色が今日どのように適用できるかを引き続き探求し、海藻緑の使用を現代施設に拡大する可能性や、「Parts List」フォントを産業美学を捉えるデザインツールとして推進する計画です。

2026/03/24 7:06

**クラウドフレアのGen 13サーバー:** コア数とキャッシュ容量を入れ替えて、パフォーマンスを2倍にしています。

## Japanese Translation: Cloudflare は、AMD EPYC 5th‑Gen「Turin」CPU と Rust ベースのリクエストハンドラ FL2 を搭載した新しい Gen 13 エッジサーバーをデプロイ完了しました。Turin はコア数が倍増(最大 192 コア、Gen 12 の 96 コアに対して)し、Zen 5 により IPC が向上、1 コアあたりの電力消費が約32%削減され、DDR5‑6400 メモリバンド幅をサポートします。チップは全コアで 384 MB の L3 キャッシュしか共有せず、1 コアあたり約 2 MB(Gen 12 の 3D V‑Cache を搭載した場合は 12 MB/コア)です。 元の FL1 ハンドラ(NGINX/LuaJIT)は Turin 上で L3 ミス率が高く、ミスサイクルが約350回に対しヒットは約50回と遅延が増大し、スループット向上にもかかわらずレイテンシが悪化しました。プリフェッチャーの調整、ワーカースケーリング、および NUMA コアアフィニティの最適化を行っても、スループットはわずか 5 % 未満にしか改善されませんでした。FL2 の軽量メモリアクセスパターンはこのボトルネックを解消し、Turin 上で Gen 12 に比べ約 50 % 低いレイテンシ、62 % 高いスループット、および FL1 より CPU あたり 2 倍のリクエスト数を実現します。 Gen 13 が Cloudflare のグローバルエッジネットワーク全体に完全展開されたことで、同社はサーバー数を減らしつつより多くのトラフィックを処理できるようになり、SLA に縛られたレイテンシを維持したままで最大 2 倍のスループットを達成します。これにより、パフォーマンス・ペー・ワットが約 50 % 改善され、ラック単位でのスループットは約 60 % 向上します。結果として CDN とクラウド顧客双方の運用コスト削減とカーボンインパクト低減に寄与します。