自宅でできる Chromium Code Search


概要

巨大なプロジェクトのコード全文検索するとき、どのようなツールを使用されていますか?
GNU grep はすべてのファイルを毎回検索するためかなりの時間を必要としますし、git grep も同じキーワードであれば2回目からはキャッシュが若干効くものの、やはり検索に10秒以上待たされると思考が途切れてしまいます。

本稿では Chromium 開発者向けに Google が提供している Chromium Code Search と(ほぼ)同じ環境が実現できる zoekt を使用し、自端末に超高速コード検索環境を構築する方法を紹介します。

Chromium Code Search - The Chromium Projects
https://cs.chromium.org/

テスト環境

Ubuntu 18.04.3 LTS
go version go1.10.4 linux/amd64
https://github.com/google/zoekt/ dd9b88b

事前準備

まず、ターゲットとする何らかの巨大プロジェクトを準備します。もし適当なプロジェクトがなければ、Chromium 公式のビルドインストラクションに従い Chromium のコードを取得してください。

git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git
export PATH="$PATH:${HOME}/depot_tools"
mkdir ~/chromium && cd ~/chromium
fetch --nohooks chromium

注:本稿作成の時点で30GB超あり、fetch にかなりの時間を必要とします。

go環境のセットアップ

zoekt は go で実装されています。
go が未インストールの場合は、apt(apt-get)で golang をインストールしてください。

sudo apt install golang

zoekt のインストール

zoekt 本体 のインストールは README のとおり、go get コマンドでOKです。

go get github.com/google/zoekt/

インデックスの作成

引き続き、インデックス作成のため zoekt-index をインストールし、対象ソースの検索インデックスを作成してください。

go install github.com/google/zoekt/cmd/zoekt-index

ここで、今回 goパッケージ管理を使用していないことで、依存パッケージの不足でエラーが出力されることがあります。

go/src/github.com/google/zoekt/cmd/zoekt-index/main.go:30:2: cannot find package "go.uber.org/automaxprocs/maxprocs" in any of:
        /usr/lib/go-1.10/src/go.uber.org/automaxprocs/maxprocs (from $GOROOT)
        /home/(user)/go/src/go.uber.org/automaxprocs/maxprocs (from $GOPATH)

適宜、不足の go パッケージを手動インストールすれば、zoekt-index のインストールに成功するはずです。

go get go.uber.org/automaxprocs/maxprocs

ターゲットのソースディレクトリに移動し(ここではchromium)、インデックスを作成します。

cd src
$GOPATH/bin/zoekt-index .

検索用WEBサーバのインストールと起動

作成したインデックスはコマンドラインからも検索できますが、ここでは検索用WEBサーバを使用します。

go install github.com/google/zoekt/cmd/zoekt-webserver

ここでも go パッケージの不足でエラーが出力されることがあるため、不足パッケージを手動インストールしてください。

/home/(user)/go/src/github.com/google/zoekt/shards/watcher.go:26:2: cannot find package "github.com/fsnotify/fsnotify" in any of:
        /usr/lib/go-1.10/src/github.com/fsnotify/fsnotify (from $GOROOT)
        /home/(user)/go/src/github.com/fsnotify/fsnotify (from $GOPATH)
/home/(user)/go/src/github.com/google/zoekt/shards/shards.go:28:2: cannot find package "golang.org/x/sync/semaphore" in any of:
        /usr/lib/go-1.10/src/golang.org/x/sync/semaphore (from $GOROOT)
        /home/(user)/go/src/golang.org/x/sync/semaphore (from $GOPATH)
go get github.com/fsnotify/fsnotify
go get golang.org/x/sync/semaphore

zoekt-webserver を起動します。

$GOPATH/bin/zoekt-webserver -listen :6070

既存のポートとの衝突等でエラーが出力されなければ、指定のポートでWEBサーバが起動しているはずです。

RAM DISK(tmpfs)による高速化

ここまでの作業でも十分な検索速度を得ることができますが、動作環境の RAM に余裕がある場合インデックスをRAM DISK(tmpfs)に置くことで更なる高速応答が期待できます。

mv ~/.zoekt ~/.zoekt.org
mkdir ~/.zoekt
sudo mount -t tmpfs -o size=8G tmpfs ~/.zoekt
cp ~/.zoekt.org/* ~/.zoekt
$GOPATH/bin/zoekt-webserver -listen :6070 &

ブラウザの開発者ツール等で検索の応答時間を確認すると、100m秒強で応答していることがわかります。

以上で作業は終了です。お疲れさまでした。