Cedar-14 のメモリ使用量のテスト
最終更新日 2022年01月27日(木)
Table of Contents
Cedar-14 スタックはサポートが終了します。できるだけ早く、ご使用のアプリをサポート対象のスタックにアップグレードしてください。「Cedar-14 End-of-Life FAQ」(Cedar-14 のサポート終了に関する FAQ) も参照してください。
Cedar-14 スタックに対する取り組みの一環として、アプリのベンチマークを行い、Cedar から Cedar-14 にシステムライブラリを変更することでアプリのパフォーマンスに実際にどのような違いが現れたかを確認しました。判明したことの 1 つは、一部のアプリではメモリの動作がスタック間で異なることです。それらの違いをさらに詳しく調査し、この記事で結果を紹介します。
メモリ使用量をチューニングおよび最適化する方法についての詳細は、「glibc メモリ動作のチューニング」の記事を参照してください。
glibc の malloc 実装の根本的な変更により、Cedar-14 の方が Cedar よりもメモリ使用量が多くなる可能性があります。通常は、この変更により、アプリがスレッドからメモリ割り当てを行うときのアプリのパフォーマンスが改善されます。これは、より多くのメモリアリーナがアプリで利用できるためです。このため、多くのスレッドを作成する (また、内部で glibc の malloc 実装を使用する) アプリのパフォーマンスは、Cedar-14 では異なったパフォーマンス特性を示す可能性があります。
glibc でメモリアリーナを管理する方式は、環境変数 MALLOC_ARENA_MAX
を設定することによって微調整できます。
テスト結果
この記事で紹介するテストでは、Cedar をベースラインとして使用し、MALLOC_ARENA_MAX
の値をさまざまに変えて Cedar-14 と比較しました。テスト候補は、Puma Web サーバーを使用するように設定された Ruby アプリでした。
メモリ使用量 (RSS) の平均 (ベースは Cedar)
設定 | 倍率 |
---|---|
Cedar-14 | 1.73x |
Cedar-14 (MALLOC_ARENA_MAX=1 ) |
0.86x |
Cedar-14 (MALLOC_ARENA_MAX=2 ) |
0.87x |
Cedar-14 では Cedar よりメモリ消費量が多かった一方、dyno で使用可能な 512 MB をこのアプリが一度も超過しなかったことは注目に値します。
応答時間平均の中央値 (ベースは Cedar)
設定 | 倍率 |
---|---|
Cedar-14 | 0.90x |
Cedar-14 (MALLOC_ARENA_MAX=1 ) |
1.15x |
Cedar-14 (MALLOC_ARENA_MAX=2 ) |
1.03x |
応答時間平均の 95 番目のパーセンタイル (ベースは Cedar)
設定 | 倍率 |
---|---|
Cedar-14 | 0.91x |
Cedar-14 (MALLOC_ARENA_MAX=1 ) |
1.41x |
Cedar-14 (MALLOC_ARENA_MAX=2 ) |
1.03x |
64 ビットシステム上の glibc でのメモリプールのデフォルトの数は CPU コアの数の 8 倍です (Heroku 上の dyno で確認される CPU コアの数は dyno タイプによって異なる)。
アリーナの数をこのデフォルトよりも制限すると、通常、メモリ使用量が減少します。"1" と “2” の値でテストした結果はどちらも、同程度のメモリ減少となりました。ただし、アリーナ値 “1” と “2” ではパフォーマンスの違いは顕著です。特に、"1" は “2” よりもパフォーマンスが低下します。MALLOC_ARENA_MAX
に値を設定しない場合、デフォルトの glibc の動作になり、パフォーマンスは最高になりますが、メモリ消費は最も多くなります。MALLOC_ARENA_MAX
を使用してアプリのパフォーマンスを最適化する方法についての詳細は、「glibc メモリ動作のチューニング」の記事を参照してください。
どのようにテストしたか
Ruby gem リポジトリである Bundler API は Heroku 上で動作し、Heroku はそのメンテナンスに貢献しています。これにより Heroku では、さまざまな glibc 設定を持つ複数のスタックでテストを実行できます。
本番アプリのログを読み取り、複数のステージングアプリですべての有効なリクエストを再現するサービスを構築しました。各ステージングアプリでは最新リリースの Bundler API を実行しましたが、設定は独立していて、リソースも完全に分離されていました。
テストは合計 24 時間にわたって実行されました。