Research Institute of Characteristic Creation

Takashi Osako's development project.

処理系性能評価のためのシステムならびにアプリケーションの解析

※ 付録資料ならびに当日プレゼンテーションした分のスライドはこちらです.

処理系性能評価のためのシステムならびにアプリケーションの解析:資料版 - Google スライド

大迫貴1 山崎進2

概要

本研究は,プログラミング言語処理系の性能を評価することで,処理系の性能向上によるWeb アプリケーションの高速化ならびに性能向上の余地がどの程度存在するのかを検証する.また,Web アプリの実態に近い機能感ならびに操作感で検証するため,Web システムのチューニングを競う大会であるISUCON の予選課題を用いる.具体的な調査手法としては,Linux 性能解析ツールperf を用いて,CPU やプログラムの動作に着目したプロファイリングを行い,システム全体やアプリケーションを解析する.異なる処理系にて,同一の命令を実行した際のCPU 挙動の効率性やISUCON ベンチマーカのスコアなどを考慮し,CPU バウンドと仮定した場合のシステム・パフォーマンス上のボトルネックを明らかにする.

1. はじめに

1.1 本稿の位置づけ

本研究の目的は,Web アプリのプロファイル情報を取得することにより,

  1. 潜在的なWeb アプリ性能向上の余地がどのくらい残されているのか
  2. 処理系のどこを性能向上ならびに高速化するべきか

を明らかにすることである.

本研究は,Web アプリの実態に基づき処理系を評価する点が有用である. 今回,このアプローチに取り組むため,実証課題にWeb システムのチューニングを競う大会であるISUCON の予選課題を採用した. さらに,処理系の性能解析にCPU 関連の解析ツールであるperf を用いた. これにより,Web アプリがCPU バウンドと仮定した際のシステム・パフォーマンスを明らかにすることができた.

本稿は,2019 年9 月28 日に開催された第五回Web System Architecture 研究会3にて発表した内容を中心に,WSA 研究会 のみなさまから頂いたフィードバックを元にアップデート, 強化ならびに補足するものである.本稿においては,主に ISUCON の活用とperf による性能評価についてそれぞれ述べる.

1.2 WSAにおける関心事

筆者は,Web System Architectureの領域ならびにWSA研究会の皆様にとっての関心事について,以下の手順のとおりに考察した.

  1. WebアプリがCPUバウンドなのかI/Oバウンドなのかを知りたい
  2. CPUバウンドならば,処理系の性能がWSAの性能に貢献できる
  3. CPUバウンドがどこで起きているのかを知ることで,コード最適化すべき機能が明らかになる.
  4. 1から3までを踏まえると,処理系の性能向上により,WSAがどのくらい性能向上するかが観測できる.

処理系の性能向上がWSAの性能向上にどのくらい影響を与えるのかは,WSAの領域ならびにWSA研究会の皆様にとっての関心事ではないか.

2. 用語説明

WSA

Web System Architecture の略称.ウェブを取り巻くシステムのアーキテクチャ全般を指す用語.

プログラミング言語処理系

プログラミング言語の実装についての総称を指す.本稿では,単に「処理系」と表記する.

ISUCON

Iikanjini Speed Up CONtest の略称.LINE 株式会社が主催となって開催している,Web システムやアプリのチューニング技能を競う大会を指す. 例年,Web アプリの実装がいくつかの言語で用意されており,それらの振る舞いを変えることなく性能を向上させる. 最終的には,ベンチマーカのスコアを競い,勝敗を決する.

SPA

Single Page Application の略称.Web ブラウザによるページ遷移を行うことなく,単一のWeb ページにてコンテンツの切り替えを行う実装手法を指す. ユーザー体験の向上やレスポンス改善の手法として用いられる.

perf

CPU 関連の統計情報を閲覧したり,プロファイルを取得したりできるツールである.

コード最適化

プログラムの実行効率を向上させるために,コードの設計や記述内容を調整することを指す.

ISUCONの活用

3.1 ISUCONを活用するメリット

筆者は,ISUCONを本研究に活用するメリットとして次を挙げる.

  1. 既存の実装を準備することなく,処理系ごとの性能を比較できる
  2. コード最適化などのチューニングが行われていないため,処理系の純粋な性能を評価しやすい
  3. ISUCONベンチマーカと呼ばれる複数の言語で実装されたWebアプリの性能を統一的な基準でスコア化する指標が準備されており,Webシステムの性能比較が行いやすい
  4. ランキング統計や参加チームのブログ記事などから,処理系に対する性能向上の余地を推測できる

基本的には,ISUCONが競技ということに由来している.

3.2 対象とする「ISUCON8予選課題」

本研究にて分析の対象とする課題は,ISUCON8(2018年開催)の予選課題「イベントのチケット管理アプリ」とする.

主要な機能としては,ユーザ認証,座席の予約や管理画面を備えている.また,主要な特徴としては,Web用MVVMライブラリVue.jsを用いたSPA風の構成である.このような構成はWebページのロジックとデータを分離できるため,マルチデバイスに対応するアプリのアーキテクチャとして,広く用いられている.

これは,この課題を分析の対象としている理由である.

3.3 システムの構成

ISUCON8の予選は,クラウド上の仮想マシンで実施された.今回は実験のためオンプレミスにて,検証に必要なシステムをセットアップした,ここで,競技時のシステムの構成を示す.

f:id:osako_ricc:20191121162056p:plain

ISUCON8の予選では,3台の競技用サーバならびに1台のベンチマーカ用サーバ(いずれは性能は同じもの)が用意された.ここで.ローカル側におけるネットワーク帯域は1Gbpsであり,グローバル側のネットワーク帯域は50Mbpsであった.

3.4 競技用サーバのアーキテクチャ

競技用サーバのアーキテクチャを示す.

f:id:osako_ricc:20191121162100p:plain

競技用サーバは,CentOS上にh2o(HTTPサーバ)がリバースプロキシとして設定されており,それと各言語の実装が接続されている.データベースサーバは,各言語の実装が共通してMariaDBを用いている.なお,今回の検証では時間の都合上,Go言語ならびにPython言語の実装のみについて取り扱うこととする.

ここで,競技時におけるサーバのスペックを示す.

vCPU 2コア Intel(R) Xeon(R) CPU E5-2640 v4 @ 2.40GHz
メモリ 1GB
ネットワーク帯域 1Gbps
ディスク SSD

4. ISUCONの再現

競技用サーバは,構成管理ツールAnsibleを用いてプロビジョニングされていた.そのため,検証用マシンのセットアップにも同じモノを用いる.プロビジョニングは開発マシンからansible-playbookコマンドにて実行する.

$ ansible-playbook -i development site.yml

いくつか注意点がある.

プロビジョニングを実効する前に,検証マシン側のsudoesファイルを書き換え,sudoコマンドを実行したときに管理者ユーザのパスワードを尋ねないように設定しておく

また,実行時点でRubyについては処理系の実装にバグがあり,それが原因でAnsibleタスクが途中で止まってしまう.今回の検証では,Rubyについては触れないため,インストールするRubyのバージョンを2.5.1から2.6.3に変更することで対応した.]

ここで,検証マシンのスペックを示す.

CPU 4コア:AMD Ryzen 2500U @ 2.0 GHz ~ 3.6 GHz
メモリ 8GB
ネットワーク帯域 1Gbps(優先接続)
ディスク M.2 SSD

検証マシンのスペックは,競技用サーバーのスペックに比べ,大きく余裕のある構成になっている.

4.2 初期状態のスコア

参照実装の初期状態におけるベンチマーカーのスコアを測定した.測定は連続で3回実行し,そのスコアの平均値を比較値とした.小数点第1位を四捨五入している.

回数/言語 Python Go
1回目 455 1152
2回目 325 939
3回目 378 1100
平均 386 1064

Go実装の方が,Python実装よりもスコアが高い傾向にあることがわかる.スコアの誤差は各実装それぞれ許容範囲内(相対誤差±20%)となっており,この結果は確からしい.すなわち,Go実装とPython実装の性能比は約3倍程度となり,有意差が認められる.

Pythonはシングルスレッド処理,Goはマルチスレッド処理が得意だと一般的には言われているが,その結果が示されたのではないだろうか.

5. リソースモニタによる並列化度の推定

5.1 リソースモニタによる分析

リソースモニタは,CPU,メモリやスワップの状況を視覚的に把握できるツールである.CPU動作の傾向を把握するのに最も適しているツールであるといえる.ここでは,Go実装とPython実装のベンチマークにおいて,最も負荷がかかりはじめている部分を抜粋し,分析を行う.重要なことを記すが,これらの分析はすべて目視である.

f:id:osako_ricc:20191121165516p:plain

f:id:osako_ricc:20191121165518p:plain

CPU使用率に着目すると,平均的にGoの方がCPU使用率が若干低いことがわかる.また,Go実装の方がPython実装に比べて,コアごとのCPU使用率が分散していることがわかる.

なお,メモリ,スワップやネットワークの値に大きな変動はなかった.

5.2 システム並列化度の推定

リソースモニタの推移から,システムの並列化度を推定する.ここでいう,システムの並列化度とは.次のようなものである.

リソースモニタから,Goの場合は処理全体の
* 80%が4物理コアで並列処理
* 20%が1物理コアで逐次処理
をしていたと推測される.

これは,Go言語における推測の結果である.これは,次のような図と説明により求められる.

f:id:osako_ricc:20191121165527p:plain

Go実装はうまく並列処理が行われているが,CPU使用率が80%くらいで止まっている.これは,CPUにおいて並列処理された部分(図の下側の部分)と逐次処理された部分(図の上側の部分)があることを示している.CPUの使用率が80%程度で止まってしまった理由としては,並列処理のための同期排他制御が関係していると考えられる.以上の考察により,Go実装におけるシステムの並列処理性能を導出した.

Python実装における,推測の結果を次に示す.

リソースモニタから,Pythonの場合は処理全体の
* 25%が4物理コアで並列処理
* 75%が1物理コアで逐次処理
をしていたと推測される.

これは,次の図に示される面積の割合にて求めたものである.Pythonは,Goは対照的にコアごとのCPU使用率に差がある.これを用いて,システムの並列化度を参照するには,リソースモニタの推移を面積で捉えれば良い.

f:id:osako_ricc:20191121165539p:plain

以上の考察により,Python実装におけるシステムの並列処理性能を導出した.

6. perfによる性能解析

6.1 perfとは

CPU周辺の解析ツールについて,次の表に示す.

ツール 説明
uptime ロードアベレージ
vmstat システム全体でのCPUアベレージが含まれる
sar 履歴的な統計
ps プロセスのステータス
top プロセス/スレッドごとのCPU使用状況
pidstat プロセス/スレッドごとのCPU利用の分析
time コマンド時間の分析,CPU利用の分析を含む
DTrace, Perf CPUのプロファイリングとトレーシング
perf CPUパフォーマンスカウンタ分析

perfは,「CPUのプロファイルとトレーシング」「CPUパフォーマンスカウンタ分析」の2つに当てはまる.

6.2 perfの活用

perfはLinuxカーネル2.6.31以降で利用できる.CentOSであれば,yumコマンドでperfを導入する.

$ sudo yum instal perf

筆者は,perfを本研究に活用するメリットとして次を挙げる.

  1. パフォーマンスカウンタ統計から,プログラムコードがどのくらい効率よく実行しているかわかる.よって,処理系のコード最適化の性能を計測できる
  2. プロファイル情報から,プログラムの中のどのコードが実行されているかを特定できる.ソースコードと照らし合わせることで,どのコード最適化機構が働いているのかわかる.
  3. 処理系の性能計測では,I/OバウンドよりCPUバウンドへの関心が強い.PerfはCPUバウンド処理の計測に効果を発揮するので,この研究における検証に最適である.
  4. プロファイル計測時のオーバーヘッドが比較的少ないとされる

基本的には,perfがCPUの生データを取得ならびに閲覧できることに由来している.

6.3 データの測定

perfを用いて,ISUCONベンチマーク負荷時のCPUサイクルカウンタを測定した.測定時のコマンドは,次のとおりである.

# perf stat -a

計測データは,付録資料に示す.

今回の分析となる,CPI/IPCの分析に必要なデータをピックアップした.

Python Go
cycles 217,068,757,941 883,790,282,948
instructions 197,102,377,369 431,025,301,648
IPC 0.91 0.49

表4より,次のことがわかる.

  • Python実装はGo実装に比べて命令実行の効率が悪い.
  • CPIが1を超えることは,システムの並列性が大きいことを意味する.これらは,パイプライン処理が有効に働いている,命令のデータに局所性がある,複数コアによって並列化されているため効率よく働いている,などの理由が考えられる.

7. CPIならびにIPCの補正

7.1 計測の対象

perfから計測された値は,CPUが理想的に並列化された状態で稼働しているときのCPIとみなすことができる.そのため,システムの並列化されない部分を含んでのCPIを求めるには,実効時間に基づく並列化度pを求めて,補正した値を計算する必要がある.

7.2 アムダールの法則

アムダールの法則により,ある高速化手法によるスピードアップを求めることができる.

f:id:osako_ricc:20191121171255p:plain

よって,

f:id:osako_ricc:20191121171313p:plain

が導かれる.

7.3 補正後

CPIならびにIPCを補正したものを次の表に示す.補正手順については,付録資料に示す.

Python Go
CPI 0.63 0.60
IPC 1.58 1.66

次のことがわかる.

  • アムダールの法則を用いた補正後のCPIは物理コアの稼働状況を反映している
  • 補正前のCPIと補正後のCPIでは,同程度の値となった.これは,Goの方がPythonよりマルチコア性能が良く,またPythonがGoよりもスーパースカラの命令並列性を有効活用している.すなわち,Pythonのほうがコード最適化性能は優れている.

8. 考察

8.1 処理系の相対的な比較

本研究では,処理系の性能を比較した際の,相対的な比較ができた.

並列処理性能:Go > Python
コード最適化:Python > Go

今回のリソースモニタとperfを用いるアプローチにより,処理系の並列処理性能とコード最適化を指標化できることがわかった.

9. 将来課題

9.1 測定の厳密・自動化

リソースモニタによる並列化度の推定においては,目視でその判断を行った.正確に並列化度を判断するためには,CPUごとの使用率を一定間隔で取得し,またベンチマークのログを突き合わせ,最も確からしい範囲で比較する必要がある.

9.2 コールグラフ解析のマイクロベンチマークへの適用

今回は,ISUCONをマクロベンチマークの題材として選択した.今後は,関数呼び出しを記録するコールグラフを分析する.それに加えて,ISUCONベンチマークを改良し,マクロベンチマークよりも粒度が細かいマイクロベンチマークを分析する.これらにより,システム上のパフォーマンス・ボトルネックを詳細に解析する.