Systems Performanceとは
Systems Performanceとは、特にWebアプリケーションのための性能改善をテーマにした書籍。 さまざまな障害や性能悪化に関するケーススタディが登場し、それに対してどのように調査するか?どのように改善するか?のテクニックが取り上げられている。
私はどちらかというとソフトウェア開発をメイン業務としてやっていることが多いが、Systems Performanceはソフトウェアエンジニアも読むべき本だと思う。 ソフトウェアをつくるにあたって、どうして◯◯をしたら性能がよくなるのか(あるいは悪くなるのか)という視点を、様々な例を挙げて説明してくれている。
まっとうにLinuxの教科書的な本を読むのはなかなかハードルが高いし、読んだはいいけど頭に入らないこともあるが、こういった切り口の本だと勉強のモチベーションが保ちやすい人も多いのではないだろうか。
おすすめの副読本
Systems Performanceだけだと、Linuxの基礎知識の解説が弱い(というかほぼない)ので、以下の本も用意して適宜調べながら読み進めていくとよい。
引用
性能の分野は以下を含んでいる。1から順にやっていく。
1. Setting performance objectives and performance modeling
2. Performance characterization of prototype software or hardware
3. Performance analysis of development code, pre-integration
4. Performing non-regression testing of software builds, pre- or post-release
5. Benchmarking/benchmarketing for software releases
6. Proof-of-concept testing in the target environment
7. Configuration optimization for production deployment
8. Monitoring of running production software
9. Performance analysis of issues
-
Proof of concept
- フィジビリスタディのときの概念実証、デモンストレーション
-
1から5まではCIとかでやってる部分。6のProof of concept testingで、実際にデプロイしてみて検証。その後設定を修正する
- 6以降で発覚する問題というのは、開発(コーディング)段階で気づけなかった問題ということ
-
性能試験は先送りにされがちが、開発段階で性能試験をやらないとアーキテクチャの修正が難しくなる
-
性能試験観点には以下がある
- workload analysis
- アプリケーション側での観点。ワークロード(計算資源)を見る。load average値のことと思われる
- resources analysis
- workload analysis
-
テクノロジーはsubjective(主観的)
- エラーははっきり表明される
-
性能はobjective(客観的)
- たとえばdisk i/oのレスポンスタイムが1msだったとして、それが性能が悪いかどうか言い切れるのか?
- アプリケーションの種類やユーザーにもよる
- 目標値を決めることによってsubjectiveにできる。方法論は2章で紹介
-
性能問題は複雑
- いろいろな事象が関連している。あるボトルネックを潰すと別のボトルネックが出てくることがある
- 環境が変わると再現しないことも…
-
性能問題を見つけた=解決ではない
- 問題の規模をあらわすことはできる
- 小さい問題なのか?大きな問題なのか?エンジニアのリソースを費やすべきなのか?
- latencyはよいメトリクスになる
-
latency
-
待ち時間の目安になる
-
DBの例。クエリを投げて返答に100msかかったが、そのうち80msはio waitだった。最高で20msで返答できるはずなので、5倍遅い計算ということが見積もれる
-
IOPSを見ればいいというわけではない。あるIO operationが重い処理だったら回数を減らしても意味が無い
-
dtraceとdtrace用のD言語(by Sun Microsystems)を使うとより詳細な解析ができる
-
cloud computing
- 複数のtenant(サービスプロバイダ、多分AWSなど)にまたがってリソースを管理する難しさもある
- 物理的な(ハードウェアでの)問題か判別できるか?
- diskだったら隣にあるdiskによって性能劣化している場合がある
- tenantについては物理面での監視情報を提供していないことがあるため、ハードウェアの問題なのか、ソフトウェアの問題なのかの切り分けが難しくなる場合がある
- 複数のtenant(サービスプロバイダ、多分AWSなど)にまたがってリソースを管理する難しさもある
Case Studies
- DBのloadはいつもどおりだった。クエリの発行数は通常通り。CPUの使用率が平常だったのとも一致しそう
- ここで出てくる/proc以下のdisk error counterはLinuxでどう見るのか不明。Solarisの
iostat -e
ではエラー数情報が取得できるようなので(iostat(1M) (man pages section 1M: System Administration Commands))、Solarisの話なのかも。 smartctl
というソフトウェアを使ってディスクの診断をしているという情報あり。/sys/class/scsi_disk/*/device/ioerr_cnt
で、Redhat7@Vagrant環境でエラーカウントらしきものは確認できた。ただ、Amazon Linux@AWSではscsi_diskというディレクトリがなかった。デバイスドライバが関係している?(The Linux Kernel: デバイスドライバ)
- ここで出てくる/proc以下のdisk error counterはLinuxでどう見るのか不明。Solarisの
- CPU以外でI/O loadが上がる原因はないか?同僚に聞いたところ、diskの使用率が100%に達するとfile system fragmentationが発生するとのこと。しかし実際のディスク使用量は30%だった
- その他に原因はないだろうか?Kernel I/Oの知識から考えてみる。disk I/Oはfile system cache(page cache)にヒットしない場合に多大に影響される。
- file system cache hit rateを調べてみる。1現在のヒット率は91%。これは高いようだ。他の同様な作業をするDBサーバは97%以上だった。また、file system cache sizeは他のサーバよりもとても大きかった
- Dbサーバ上で稼働するアプリケーションに、メモリ使用率が高いものがあった。他のアプリケーションがメモリを使っていると、ファイルキャッシュに割り当てる領域が少なくなってしまうため
I/O バッファキャッシュについて
「Linux プログラミングインターフェース」を読んだメモ。
- write()/read()は実際にはメモリ上のバッファの読み書きをしている。
- write()時は一度メモリ上のバッファに内容を保持してから、後でカーネルがdiskに書き込む。read()の場合は
- プロセスとリソースについて
- カーネルはプロセスごとに、コンピュータリソースの割当をおこなう。メモリは起動時に割り当てて、その後随時割当量を変える。CPUやネットワークは割当を決めないが、すべてのプロセスに公平に分配されるようにする
- メモリマッピング
- ファイルへのアクセスはfile mapping。これとは別にanonymous mappingというものがあり、これは対応ファイルを持たない。 さらにmappingにはshared mappingとprivate mappingがある。private mappingは自プロセスに閉じ、対応ファイルにも反映されない。shared mapping の場合は他のプロセスからも参照でき、ファイルにも反映される。(通常ファイル書き込みはshared mappingとおもわれる)
Linux カーネルはバッファキャッシュのサイズを固定しません。必要に応じメモリページを割り 当てますが、システムの実装メモリサイズと他のプロセスが必要とする物理メモリ(プロセスの実 行に必要なテキスト、データを維持するだけのメモリ)によりその上限が判断されます。使用可能 なメモリが少なくなれば、カーネルは変更されたバッファキャッシュのメモリページをディスクへ書き出し、そのページを再利用します。
- 使える物理メモリが少なくなると、バッファキャッシュのメモリページをディスクへ書き出す。なので、disk i/oが増える
- 書き出されるファイルをスワップファイルという。
プロセスが物理メモリ上に現在存在しないページを参照すると、ページフォールト(page faultページフォルト)が発生し、そのページがディスクからメモリへロードされるまで、カーネルがプロセスの実行を一時停止します。
- とある。なのでスワップファイルができているとプロセスの処理がブロックされる可能性が出てくる
- read()はキャッシュがなければdiskへアクセスするが、write()は必ずメモリ上のバッファへの書き込みになる.一旦バッファに書き込んでからカーネルがdiskに書き込む
- non-regression-testing
- 新しいリリースがあるときに、以下の方法でテストする
- Benchmarkを決める
- できるかぎりソフトウェアのいろいろな機能を使う
- 2を以前のバージョンと新しいバージョンで実行し、Benchmarkを比べる
- 新しいリリースがあるときに、以下の方法でテストする