gitリポジトリ向けの高速ctagsラッパー：ptags

# はじめに
gitリポジトリ内のソースコードを高速にctagsするツールptagsを作りました。
複数のctagsを並列実行するので普通に`ctags -R`するより最大5倍程度速いです。
またデフォルトで`.gitginore`を考慮するので、excludeオプションで除外する必要もありません。

このツールはRustで作成しました。簡単なソースコードの解説も書きましたので興味のある方は以下の記事もどうぞ。
[gitリポジトリ向けの高速ctagsラッパー：ptags（ソースコード解説）](https://qiita.com/dalance/items/6f19b7b3132430eea76f)

# インストール
[リリースページ](https://github.com/dalance/ptags/releases)からダウンロードしてPATHの通ったところに展開してください。
あるいは[`cargo`](https://crates.io)がインストール済みなら以下でもOKです。

```console
> cargo install ptags
```

また、ツール内部で`git`と`ctags`を呼ぶのでこれらも必要です。
動作確認したバージョンは以下の通りです。
（`git-lfs`は`--exclude-lfs`オプションを使うときだけ必要です）

| Command   | Version                                               |
| --------- | ----------------------------------------------------- |
| `ctags`   | Universal Ctags 0.0.0(f9e6e3c1) / Exuberant Ctags 5.8 |
| `git`     | git version 2.14.2                                    |
| `git-lfs` | git-lfs/2.3.3                                         |


# 使い方
デフォルトで`ctags -R`と同じ動作（カレントディレクトリから再帰検索）です。
gitリポジトリ外では動作しませんが、その代わり`--exclude-lfs`や`--include-untracked`などgitリポジトリ上の扱いに応じてinclude/excludeを切り替えることができます。

また、以下のようにctagsのオプションも渡すことができます。

```console
> ptags -c --links=no -c --languages=Rust
```

オプション一覧は以下の通りです。

```
ptags 0.1.6-pre
dalance@gmail.com
A parallel universal-ctags wrapper for git repository

USAGE:
    ptags [FLAGS] [OPTIONS] [--] [DIR]

FLAGS:
        --exclude-lfs          Exclude git-lfs tracked files
    -h, --help                 Prints help information
        --include-ignored      Include ignored files
        --include-submodule    Include submodule files
        --include-untracked    Include untracked files
    -s, --stat                 Show statistics
        --unsorted             Disable tags sort
        --validate-utf8        Validate UTF8 sequence of tag file
    -V, --version              Prints version information
    -v, --verbose              Verbose mode

OPTIONS:
        --bin-ctags <bin_ctags>           Path to ctags binary [default: ctags]
        --bin-git <bin_git>               Path to git binary [default: git]
    -e, --exclude <exclude>...            Glob pattern of exclude file ( ex. --exclude='*.rs' )
    -c, --opt-ctags <opt_ctags>...        Options passed to ctags
    -g, --opt-git <opt_git>...            Options passed to git
        --opt-git-lfs <opt_git_lfs>...    Options passed to git-lfs
    -f, --file <output>                   Output filename [default: tags]
    -t, --thread <thread>                 Number of threads [default: 8]

ARGS:
    <DIR>    Search directory [default: .]
```

# ベンチマーク
githubから適当なリポジトリを取ってきて比較しました。ディスクI/Oの影響を受けないよう、事前に一度実行してリポジトリの中身がディスクキャッシュに載った状態から測定開始しています。結果は10回の平均値です。

## 測定環境

- CPU: Ryzen Threadripper 1950X
- MEM: 128GB
- OS : CentOS 7.4.1708

## データ

| Name    | Repository                           | Revision     | Files  | Size[GB] |
| ------- | ------------------------------------ | ------------ | ------ | -------- |
| source0 | https://github.com/neovim/neovim     | f5b0f5e17    | 2370   | 0.1      |
| source1 | https://github.com/llvm-mirror/llvm  | ddf9edb4020  | 29670  | 1.2      |
| source2 | https://github.com/torvalds/linux    | 071e31e254e0 | 52998  | 2.2      |
| source3 | https://github.com/chromium/chromium | d79c68510b7e | 293205 | 13       |

## 測定結果
実行時間の比較はこちらになります。
<img src=https://qiita-image-store.s3.amazonaws.com/0/84296/c513ba74-d692-cb74-b57a-9fc4ada68b25.png width=50%>

ctagsを1にしたときの性能比較（大きいほどよい）はこちら。最大でctagsから5倍程度高速化しています。
<img src=https://qiita-image-store.s3.amazonaws.com/0/84296/ba3fca55-37ce-96e1-a435-a9001ddf1e9a.png width=50%>