自宅でできる 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 のコードを取得してください。

https://chromium.googlesource.com/chromium/src/+/master/docs/linux/build_instructions.md

``` bash
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 をインストールしてください。

``` bash
sudo apt install golang
```

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

https://github.com/google/zoekt

``` bash
go get github.com/google/zoekt/
```

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

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

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

``` bash
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 のインストールに成功するはずです。

``` bash
go get go.uber.org/automaxprocs/maxprocs
```

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

``` bash
cd src
$GOPATH/bin/zoekt-index .
```

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

``` bash
go install github.com/google/zoekt/cmd/zoekt-webserver
```
ここでも go パッケージの不足でエラーが出力されることがあるため、不足パッケージを手動インストールしてください。

``` bash
/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)
```

``` bash
go get github.com/fsnotify/fsnotify
go get golang.org/x/sync/semaphore
```

zoekt-webserver を起動します。

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

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

http://example.com:6070

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

``` bash
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秒強で応答していることがわかります。

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