GitLab魔改造カンファレンスで発表してきました
2/6(Thu) に株式会社ドリコムとピクシブ株式会社の合同で GitLab 魔改造カンファレンスが行われました
会場はドリコムさんのオフィスでとてもおしゃれな感じでした
ドリコム攻めに来ました
— 麺類 (@catatsuy) February 6, 2014
ドリコム綺麗すぎて圧倒されてる
— 麺類 (@catatsuy) February 6, 2014
ドリコムさんから 3 人,ピクシブからも私を含めて 3 人が発表しました
私が発表した理由として,ピクシブでは一部のサーバーを除いてサーバーの root をインフラの人間しか持てません
なので GitLab など新しいツールを使うにはインフラの協力が不可欠なのですが,私が GitLab 導入を提案した一人だったので成り行きで GitLab 導入やその後の運用を適当な感じでやっていました
そんな中,魔改造カンファレンスの話が回ってきたので私が発表する感じになったのが流れです
と前置きはこれくらいにして発表ですが,発表内容は簡単に言うと『GitLab の git アクセスをしている grit が遅いし闇だから rugged に書き変えたかったけど色々あった挙句に出来なかったよ!!』という魔改造カンファレンスなのに改造を全くしないプレゼンでした
そしてこの発表をした数時間後に
GitLab is moving from Grit to Rugged to save memory and gain speed. https://t.co/Wv6y2q51l0 Help in the form of merge requests is welcome.
— GitLab (@gitlab) February 6, 2014
と公式がツイートしていて爆笑しました
これからプルリクしていきたいですね
発表資料
内容
GitLab の気になるところ
- 遅い
- 特にコミットやマージリクエストの diff を取るところが遅い
- IO が刺さっているわけではない
- slow query も出ない
- では一体何が原因なのか?
Git の読み込みが遅い
- Git の読み込みが遅いと気付く
- 調査して直せないのか考えた
- 時間足りなくて直すフェーズまで間に合わず…
- とりあえず出来たところまで共有
grit 特徴 #1
- Git のオブジェクトファイルや,git のコマンドの実行結果をゴリゴリやっている
- 子プロセスの起動したり,ファイルをパースしたり…
- ソースコードもだいぶ闇
- ドキュメントが貧弱
- オブジェクト指向や ActiveRecord を少し意識したような API 設計
grit 特徴 #2
- 本家のリポジトリは既に更新が停止していて,色々な Fork がある
- ソースコードもあまり綺麗でなく,メンテナンスをする気がある人があまりいない印象
- GitLab が使っているのは独自 Fork(今回使用するのはこれ)
- 最もメンテされている grit と思われる
- しかし GitLab 以外から使われていることは考慮されていない
- GitHub 本家も Fork してる
- 最近更新はない
rugged 特徴
- libgit2 の Ruby バインディング
- libgit2 は C 実装で事実上の git の再実装
- GitHub も使っているらしい
- C の API をバインディングしているだけなので git の実装がかなり生で出ている
- git の内部の知識がないと使うのが難しい
- コマンドラインの使い方しか知らない人には使いにくい
- C 実装だからか,Fork は少ない(スターは多い)
- rugged に関するドキュメントは少ない
- libgit2 はある
- 将来的には GitLab も使いたいらしい(本気度は不明)
grit vs rugged
gem | grit | rugged |
---|---|---|
implementation | pure ruby | C extension |
service | GitLab | Github |
speed | slow | high speed |
document | little | little |
grit 仕様
- grit で diff を取るとき子プロセスを立ち上げて git のコマンドを叩く
- かなり遅いはず
- GitLab で時折詰まったように感じるのはここ
- コミット一覧はログからゴリゴリやる
- Ruby だと文字列操作や配列の末尾に要素追加などは遅い
- grit だと大きすぎる diff を取ろうとすると例外で落ちる
Grit::Git.git_max_size
がデフォルト 5MB でこれを大きくすると大丈夫だが,標準出力が大きくなるとかなり時間がかかる- GitLab なら
gitlab.yml
のgit: max_size
を変更する - 今回のベンチマークでは一部がこれに抵触したので変更
ベンチマーク
- grit はメソッドによっては子プロセスを呼び出す
- ruby 標準搭載の
Benchmark.benchmark
はデフォルトで子プロセスの実行時間を出力しない - 引数を渡して表示できるようにする
- ruby 標準搭載の
- コミットを 100 個の詳細情報とコミット同士の diff を 99 組取ってみる
ベンチ結果
実際にやって…
- 見たかったが,時間足りず…
- 今後の課題とし(ry
grit/GitLab バグ
- GitLab 周辺の gem は gem として登録されているにも関わらず GitLab 以外から使用することを一切考慮していない
- 単体で読み込もうとするとバグに悩まされることになる
- 自分が遭遇したバグ紹介
[gitlab_git] GitLab から使うことしか考えていない
- gitlab_git が GitLab で git を実際に触る部分
- grit を使うのはここ
- rugged を使う場合はここを大幅に書き換える必要あり
- GitLab は ActiveSupport が読み込まれるが,gitlab_git は独立した gem なので使うなら読み込む必要
- しかし一部しか読み込んでいなかった
- 具体的には
try
を使用していた
- プルリク出した
[grit] require できない #1
- Gemfile から
path:
指定で読み込むと require できないVERSION
ファイルのパスが間違えていて起動できていない- すでにプルリクが出ている
- 何ヶ月も取り込まれず放置されていた
- マージしてもらえるように催促コメントする
- マージしてもらえた!!
- 今回のベンチマークにはもちろんこのパッチを適用
- Fixed issue #32 · Pull Request #35 · gitlabhq/grit
いい話
[grit] 想定外のコミット #2
- ある commit が読み込めない
- オブジェクトファイルが想定外の形式らしい
- 正しい挙動が不明なため issue 登録
- Issue #37 · gitlabhq/grit
- git のファイルを改行などからパースをしているだけの実装なので解析結果がおかしくなることはよくありそう
[grit] 偽りのコメントアウト #3
- コメントアウトに嘘があった
git.rev_list
を呼ぶとmethod_missing
になると書いてあったが,実際は include したクラスに実装があった- プルリクしたが反応がない
- どれも古くからあるコードで何が想定された動きだったのかわからない
method_missing
の方にしても動きそうだったが,テストは通らない- Pull Request #38 · gitlabhq/grit
URL
- Git - Git Objects
- Git - Git References
- Ruby - BundlerでC拡張を含んだgemを公開する - Qiita
- gitlabhq/grit
- libgit2/rugged
- libgit2
- libgit2 API