概要
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分のボリュームを作成しました。
(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
によりベンチマークを実行します。
SSDの方はコミット数が増えていくにつれ1秒あたりのコミット数は増えていき、最終的に180commits/secぐらいのパフォーマンスになりました。まだ収束していないので、200ぐらいまでいくかもしれませんね。
逆にHDDの方はコミット数が増えるにつれてパフォーマンスが低下していきました。
(ちなみに遅くなっているのはバーストのクレジットを使い切ったわけではありませんでした。1時間で20%下がるぐらいの速度でバーストクレジットを消費していました。)
ST1が20commits/secぐらいで下限に達したようにも見えるので、アプリケーションの要件的にこれぐらいの速度で許容できるのであれば、HDDでも大丈夫そうです。
ベンチマーカ走行時間(2万コミット完了にかかった時間)はこのようになりました。
SSD系とST1の差はこんなもんかなと思っていましたが、ST1とSC1も4倍弱ぐらい差が出る結果となりました。(SC1が思っていたよりも遅かったです)
おまけ
showwin/git_benchmark に bench_monolithic.py
と bench_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
…
1つのレポジトリで全てを管理する方は2000コミットを超えたぐらいからパフォーマンスが下がっていっていることが分かります。
複数レポジトリの方が高速ですが、もちろんこちらの方ががディスク容量は食います。
比較してみるとこんな感じになりました。
bench_distributed: 1.1GB
bench_monolithic: 460MB
ちなみに、2万コミット分のファイルをそのまますべで保存すると79MBになりました。
git を使うよりも容量が少なかったです、、笑
すべて1行のみのファイルで、1行内の一部データを変更しているので、gitで管理したらそれはデータ量増えますよね…
データ量に関する検証も別でやってみたいと思います。