Edited at

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

More than 1 year has passed since last update.


概要

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で管理したらそれはデータ量増えますよね…

データ量に関する検証も別でやってみたいと思います。