TechBlogSideCIのエンジニアによる技術ブログです。Otherこの記事で説明したGitの話には、私の誤解が含まれています。コメントまで見てください。(EFSにリポジトリを置くと遅いのは本当。EFSというめちゃくちゃ便利に見えるサービスがあります。複数のEC2インスタンスで共有できるストレージ事前に容量を決める必要がない(使ったら使った分だけ増えていく)要するにNFSで、EBSと違って複数のEC2インスタンスから共有できるのが特に便利に見えます。cloneしてきたリポジトリを保存して共有するのに最適に見えます。API経由で実行できるようになりたいと考えています。(リファクタリングの話なのでサービスの強化には、すぐには繋がらないのですが......)このとき問題になるのが、GitHubからcloneしてきたリポジトリをどこに保存するかということです。複数台のWebサーバでリポジトリを共有できるとcloneが減ってより高速に実行できるできるだけローカルのリポジトリには消えて欲しくないのでデプロイが面倒になるといった問題があります。Expressなどで接続されたストレージにアクセスするよりは遅くなるはずですが、そもそもEBSにしても物理的にはネットワーク越しにアクセスしているはずですから、そんなに酷いことにはならないでしょう。考えながら試してみたところ、6倍以上もEFSが遅かったので、問題は一切解決しなかったというご報告です。https://aws.amazon.com/jp/efs/実行結果us-eastリージョンのt1.microインスタンスで試しました。Volumeとして読み書きしています。普通のEBS上のディレクトリで。0m2.396s次にEFSでマウントしたディレクトリで。cloneが終わりましたが、EFSでは2分35秒かかりました。timeの出力を見ると、realは大きく増えていますがuserとsysはほとんど変更がないので、IO待ちで遅くなっていることがわかります。EFSはこんなに遅くて大丈夫なのでしょうか。ディスクの読み書きの速度に注目して、テストしてみましょう。簡単にddでテストしてみます。MB/sEFSの場合。MB/sあれっ、速いぞ......EBSより少し遅いけど、でも速い。なんでGitだけこんなに遅いんでしょう?なんでGitだけこんなに遅いのかGitのリポジトリ操作を実装するlibgit2というライブラリがありますが、ここにgit_odb_backendという型があったりします。バックエンドというのはGitリポジトリのオブジェクトを保管する場所のことで、git_odb_backendのメンバに適当な関数ポインタを設定することで、Gitリポジトリをファイルシステムだけではなくていろんなところに保存できるように作られています。MySQLとかMemcachedとか。https://github.com/libgit2/libgit2-backendsgit_odb_backendの定義を見てみましょう。**/};https://github.com/libgit2/libgit2/blob/89c332e41b12a72d89de40d63bc568c56a2c336a/include/git2/sys/odb_backend.h色々ありますが大胆に削って、readとwriteだけで。これらの関数の型を見るとオブジェクトのIDを表しているgit_oidの数を渡す引数がないので、「えっ、こいつら一個ずつ読み書きしてるんじゃ......」ということに気づきます。それは遅いだろ......Webアプリケーションをバリバリ開発されている皆さんがよくご存知のN+1クエリという問題があります。N個のレコードを取ってくるときにN回SELECTすると遅いけど、一回のSELECTでN個取ってくると速い、というやつです。Gitのオブジェクトにも同じことが言えます。一個ずつディスクから読むと、まとめて読むより遅い。普通に接続されたディスクならそれでも十分に速く動作しますが、NFSでネットワーク越しにいちいちファイルを読み書きするとあからさまに遅かった、ということなのでしょう。いうと多分少し語弊があって、Gitでは高速に動作するよう工夫があるようです。実装があるファイルを眺めると、長々とコメントが書いてあります。(流し読みして、頑張ってるんだなーと思いました。ここら辺の話です(多分カスタムバックエンドのサンプル的な扱いになっている)MySQLバックエンドなどはわかりやすい感じで、毎回一個ずつSELECTしてくるいかにも遅そうな実装になっています。https://github.com/libgit2/libgit2-backends/blob/master/mysql/mysql.c#L370-L377残った問題GitHub.comとかはどうなっているんだろう?ところで、世界で一番Gitリポジトリを持っている組織の一つであろう、GitHubさんはどうやって実装しているんでしょう。「GFSを使っていた」などという声もありますが、現在は頑張って実装しているようです。リポジトリをローカルのストレージに保存するサーバがたくさんあるようです。2010年末に「昔はGFSだった」と言っている。2016年4月の記事なので、多分これが最新。(Gitはディスクに高速にアクセスできるときに速く動作するように最適化されているので、DGitもファイルを高速なローカルSSDに保存している。)などと書いてありますね。EBSなんでこんなに速いの?EFSが遅い理由は(間違っているかもしれませんが)納得しましたが、EBSがこんなに速い理由がむしろ気になります。EBSは一個のEC2インスタンスからしかアクセスされないので、積極的にキャッシュなどできるのかなーなどと考えています。結局SideCIはどうするの?ひとまずは、速いインスタンスを少数用意して、それぞれEBSにリポジトリを保管することにしました。GitHub.comと違ってSideCIにあるリポジトリはただのキャッシュなので、気軽に消すことができます。cloneし直さないといけないので、少し遅くなりますが、EC2とGitHub.comの通信が意外と早かったので許容範囲内ではないかという結論になりました。それで耐えられないくらい遅くなるようなら、仕方がない。我々のDGitを作ります。RSSはてなブログで読者になるスターをつけました引用をストックしましたストック一覧を見る閉じる引用するにはまずログインしてくださいログイン閉じる引用をストックできませんでした。再度お試しください閉じる限定公開記事のため引用できません。