Git
ebs
パフォーマンス計測

EBSのボリュームタイプ毎にgit commitのパフォーマンスを計測してみた

概要

EBSには4つのボリュームタイプ(高性能順にIO1, GP2, ST1, SC1)がありますが、それぞれ git commit がどれ位高速にできるのかパフォーマンスを計測してみました。

背景

なぜこんなことをしようと思ったかというと、定期的に同じページをクロールするクローラーを作っていて、クロールした瞬間のHTML or JSONを保存しておき、いつどの内容が変わったのかDiffを見たいという機能要件がありました。
取得したHTMLを何も考えずにS3に投げて、diff コマンドで差分を見る方法でも良いのですが、これだとデータ量が膨大になってしまいお金がかかってしまいます。差分だけ保存できて、またその変更履歴も簡単に追えるツール… gitでは!?となって今回技術検証のためにパフォーマンスを計測することにしました。

計測方法

計測に使ったファイルは https://github.com/showwin/git_benchmark においてあります。
5000ファイル(1ファイルあたり100B程度)に対して、20000回の変更をランダムに加え、変更毎にgit add && git commit を実行します。どのファイルに書き込むのかはランダムですが、初期状態でファイルが存在していないため、(およそ)最初の5000コミットは新規ファイル追加のcommit, 残りの15000コミットはファイルの中身が変更されるcommitということになります。

検証手順

c4.largeのインスタンスに対して、4種類のボリュームをアタッチします。
HDD系のボリュームは最小容量が500GBなので、それに合わせてSSD側も500GB分のボリュームを作成しました。
Screen Shot 2018-02-04 at 15.37.18.png
(IO1のIOPSはデフォルト値の25000から変更せずに使います)

AWSのドキュメント を参考にしてボリュームをマウントしていきます。
ホームディレクトリ配下に4種類のボリュームをマウントしました。

[ec2-user]$ ls
gp2  io1  sc1  st1
$ cd [volume_dir]
$ git clone https://github.com/showwin/git_benchmark.git
$ python3 bench_distributed.py

によりベンチマークを実行します。

結果はこのようになりました。
Screen Shot 2018-02-04 at 20.09.06.png

SSDの方はコミット数が増えていくにつれ1秒あたりのコミット数は増えていき、最終的に180commits/secぐらいのパフォーマンスになりました。まだ収束していないので、200ぐらいまでいくかもしれませんね。
逆にHDDの方はコミット数が増えるにつれてパフォーマンスが低下していきました。
(ちなみに遅くなっているのはバーストのクレジットを使い切ったわけではありませんでした。1時間で20%下がるぐらいの速度でバーストクレジットを消費していました。)

ST1が20commits/secぐらいで下限に達したようにも見えるので、アプリケーションの要件的にこれぐらいの速度で許容できるのであれば、HDDでも大丈夫そうです。

ベンチマーカ走行時間(2万コミット完了にかかった時間)はこのようになりました。
Screen Shot 2018-02-04 at 20.04.02.png

SSD系とST1の差はこんなもんかなと思っていましたが、ST1とSC1も4倍弱ぐらい差が出る結果となりました。(SC1が思っていたよりも遅かったです)

おまけ

showwin/git_benchmarkbench_monolithic.pybench_distributed.py の2つのファイルがおいてありますが、今回2種類の異なるgitレポジトリの作り方でも速度を検証してみました。
bench_monolithic.py はルートディレクトリにgitレポジトリを1つだけ作成し、レポジトリ1つで5000ファイルの変更履歴を保存する方法です。

├── benchmark_dir # git repo
│   ├── file1
│   ├── file2
│   ├── file3
│   ├── file4
…

一方の bench_distributed.py はそれぞれのファイル毎にレポジトリを作成するようにしました。

├── benchmark_dir # NOT git repo
│   ├── dir1  # git repo
│   │   └── file1
│   ├── dir2 # git repo
│   │   └── file2
│   ├── dir3 # git repo
│   │   └── file3
│   ├── dir4 # git repo
│   │   └── file4
…

io1 で比較するとこれぐらいの差になります。
Screen Shot 2018-02-04 at 17.45.04.png

1つのレポジトリで全てを管理する方は2000コミットを超えたぐらいからパフォーマンスが下がっていっていることが分かります。
複数レポジトリの方が高速ですが、もちろんこちらの方ががディスク容量は食います。
比較してみるとこんな感じになりました。

bench_distributed: 1.1GB
bench_monolithic: 460MB

ちなみに、2万コミット分のファイルをそのまますべで保存すると79MBになりました。
git を使うよりも容量が少なかったです、、笑

すべて1行のみのファイルで、1行内の一部データを変更しているので、gitで管理したらそれはデータ量増えますよね…
データ量に関する検証も別でやってみたいと思います。