Swiftコミュニティが現在取り組んでいる性能改善策の仕組みと効果

# はじめに
この記事は [NTTテクノクロス Advent Calendar 2018](https://qiita.com/advent-calendar/2018/ntt-tx)の22日目です。

ＩｏＴイノベーション事業部の須田です。
[OpenStack Swift](https://www.openstack.org/software/releases/queens/components/swift "OpenStack Swift")（以下Swift）の機能調査、運用保守を担当しています。

最近、プライベートクラウドのオブジェクトストレージサービスとして、仕組みが単純で手軽に構築でき、かつ単一点障害にも強いSwiftを選択する事業者が多くなりました。
弊社にも問い合わせやコンサルの引き合いが増えており、利用希望者の増加を実感しています。

一方、Webで「OpenStack Swift 性能」のキーワードで検索すると、残念ではありますがSwiftの性能面で色々苦労している事例が幾つかヒットします。
これはSwiftがディスクにファイルを格納する際にOSのファイルシステムを利用しており、ファイル数の増加に伴ってディスクI/O性能が低下するOSのファイルシステムの影響を受けていることが原因です。
残念ながらこの問題により性能を重視する使い方にそぐわず利用を断念した事業者も少なからず存在します。

この問題に対してSwiftコミュニティでは2018年に入って解決に向けて取り組みを始めています。
今回はその試みを紹介します。

# Swiftの性能問題
SwiftにアップロードしたファイルはOSのファイルシステムを用いてディスクに格納されます。
OSのファイルシステムはファイル毎にメタ情報（inode,dentry）をキャッシュ上に保持し、キャッシュ上のメタ情報を読み込むことで高速に処理しています。
しかし、ファイル数が増大するとメタ情報がキャッシュ上に乗り切らず、溢れたメタ情報はディスクへ書き込まれます。ディスクを介してメタ情報を処理するとファイルシステムの処理時間は大幅に伸びます。
![3_filesystem.png](https://qiita-image-store.s3.amazonaws.com/0/318729/a349fba9-e03c-47f1-89de-76096d7fb03d.png)

また、Swift推奨のフォーマットであるXFSの場合、xfsaildプロセスがメモリ上にキャッシュしたメタ情報をある程度溜まる度にジャーナルログを用いて非同期にディスクに書き出します。
ファイル数の増加に伴いinode構造（B-tree）が巨大化、複雑化することで、このxfsaild実行時にI/O負荷が高まりSwiftのI/O性能が低下します。

SwiftがOSのファイルシステムに依存している都合上、このファイル数に比例してI/O性能が低下する問題は回避できません。

弊社メンバの調査によると、数KB～数10KB程度の小さなファイルを大量（10億個程度）にアップロードした場合、Swiftの書込み性能が充填率0%の時と比べて最終的には約10分の1まで低下することが判明しています。
上記はフォーマットとしてXFSを用いた場合の測定結果ですが、同調査報告によるとext4ではより性能が劣化するという結果も出ています。

そこで発案されたのが性能改善策のLOSFです。
 
# 改善に向けた新しい試み
OSのファイルシステム上にファイル数が多く存在することでディスクI/O性能が低下するのであれば、ファイル数を減らせば解決します。
そこでSwiftにアップロードしたファイルの数を減らす仕組みとしてLOSFが考案されました。
LOSFはLots of small filesの頭文字をとった名前で、文字通り沢山の小さなファイルを改善する取り組みです。

仏 [OVH](https://www.ovh.com/world/ "OVH") 社のAlexandre Lecuyerが考案し、[OpenStack wiki](https://wiki.openstack.org/wiki/Swift/ideas/small_files/implementation "OpenStack wiki") に仕組みを掲載して[ソースコード](https://review.openstack.org/#/c/571763/ "ソースコード")も準備しています。

ファイル数を減らす仕組みは単純で、各Storageノードのディスク毎に、アップロードしたファイルとそのメタデータを１つのファイル（以下Volume）にどんどん追記していきます。
![1_volume.png](https://qiita-image-store.s3.amazonaws.com/0/318729/f6267c04-aa8d-d3af-755b-04647d82b88f.png)
これはFacebookの写真共有ストレージ「Haystack」と似た仕組みで、「Haystack」も同様に１つのファイル（Store File）にデータを追記してファイル数の削減を行っています。

ディスクにファイルを書き込む際、アップロードしたファイルとそのメタデータが１つのVolumeに書き込まれます。
次に同じディスク配下に異なるファイルが書き込まれる場合も、先程のVolumeにファイルとメタデータが追記されます。
Volumeに書き込む際にロックをかけるため、もし他のリクエストによりVolumeが捕まれていたら、別なVolumeを生成してそちらに書き込みます。
アップロードしたファイルを「どのVolumeのどの位置に書き込んだか」の情報は、各Storageノード上に新たに用意したIndexサーバのLevelDBにkey/value形式で保持します。
この情報はファイルをダウンロードする際に参照します。
![2_LOSF.png](https://qiita-image-store.s3.amazonaws.com/0/318729/152ac1c7-8fd1-1c30-56b7-882eccaefaf4.png)
このようにVolumeとIndexサーバの組み合わせによってディスクに格納されるファイル数を大幅に削減します。


# アップロード/ダウンロードの流れ
ファイルのアップロードとダウンロードの流れを整理すると以下のようになります。
## アップロード
1. アップロードしたファイルを格納するStorageノードとディスクを決定する。
2. 決められたStorageノード配下のディスクにVolumeがあればロックを取得し、無ければもしくはロックがかかっていたら新たにVolumeを作成する。
3. アップロードしたファイルとそのメタデータをVolumeに書き込む。
4. ファイルをどのVolumeのどの場所に書き込んだかの情報を、各Storageノード上のIndexサーバに非同期で通知する。
5. Indexサーバがファイルの位置情報をLevelDBにkey/value形式で保持する。


## ダウンロード
1. ダウンロード対象のファイルが格納されているStorageノードとディスクの情報を取得する。
2. 対象のStorageノードのIndexサーバに問い合わせて、目的のファイルがどこのVolumeのどの位置に書き込まれているかを取得する。
3. 目的のVolumeからファイルの中身を読み取ってクライアントに返却する。

# どれだけ性能が改善するのか
さて、それでは実際にどのくらい性能が改善するのでしょうか。
一番気になる点ですが、コミュニティから提示されている情報を記します。
## アップロード
0個の状態から400万個のファイルをアップロードした場合は1.3倍、400万個格納した状態から更に400万個のファイルをアップロードした場合は2.3倍に改善します。

* 0個→400万個

| | minutes | PUT/s |
|:----------------------|:------------------------|:--------------------| 
| 改善前 | 3360 | 19.8 |
| 改善後 | 2540 | 26.2 |

* 400万個→800万個

| | minutes | PUT/s |
|:----------------------|:------------------------|:--------------------| 
| 改善前 | 3900 | 17.0 |
| 改善後 | 1700 | 39.2 |

## ダウンロード
予め800万個のファイルを格納した状態で2.4倍に改善します。

| | minutes | PUT/s |
|:----------------------|:------------------------|:--------------------| 
| 改善前 | - | 39.0 |
| 改善後 | - | 93.0 |

ファイル数を削減する仕組みは非常に簡単ですが、性能改善の効果は高いと言えます。

# おわりに
現在コミュニティと連携して本機能のpatchをマージする準備を進めています。
もしこの機能をいち早く導入して性能を向上させたいという方がいましたら、連絡をもらえればより優先度を上げるようにコミュニティに働きかけます。

また、引き続きスループット測定やリソース(CPU使用率、memory使用量)への影響調査、リバランスの性能測定なども実施する予定ですので、測定でき次第qiitaで結果を公表したいと思います。

尚、弊社ではOSSの構築から保守、運用、移行まで幅広く提供する『[OSSクラウド基盤トータルサービス](https://www.ntt-tx.co.jp/products/osscloud/?utm_source=qiita&utm_medium=ac2018&utm_campaign=22 "OSSクラウド基盤トータルサービス")』を展開してます。
Swiftに関することはもちろん、Swift以外のプロダクトの課題にも対応できますので、OSSクラウドの導入を検討中もしくは運用でお困りの方がいましたら是非ご検討ください。