いまいちまとまってないけど公開しちゃう。
読んだところ
3. Latches
-
- Latches and Locks
- Parent and Child Latches
- Latch Gets
- Advanced Latching Control
- Reference
書かれていること
ラッチについて
要約
ラッチとは
特徴
- シンプルな仕組みなので高速。
- ラッチを獲得できるまで単純にループ(スピン)して定期的にラッチをチェックしながら待つ。ロックのようにキューイングされない。
- ラッチ取得操作には TEST AND SET、LOAD AND CLEAR、COMPARE AND SWAP などの CPU 命令が使われるため、アトミック操作が保証され、かつ高速に処理される。
- ロック操作はラッチで保護されている。以下は例。
- cache buffer locks <-- cache buffers chains latches
- row cache enqueue locks <-- row cache objects latches
- ほとんどのSGA(共有メモリ)内のデータは1つのラッチで保護されるが、データのサイズが大きくて1つのラッチで保護できない場合は、1つの親ラッチ + 複数の子ラッチで保護される。
種類
- 親ラッチ
- 子ラッチを持つ
- 子ラッチを持たない(solitary latch)
- 子ラッチ
ラッチ待機中の動作
- CPU数による挙動の違い
- 単一CPU: スリープして再要求する。
- 複数CPU: スピンして再要求する。許容回数を超えても獲得できない場合、スリープする。
- スピン
- スピンの許容回数は初期化パラメータ _SPIN_COUNT で設定できる。デフォルト値は単一CPUなら 1、複数CPUなら 2000。
- 複数CPUの場合のみスピンする。ラッチを確保しているプロセス1が CPU1 で実行中の間、ラッチを取得したいプロセス2が CPU2 でスピンするというイメージ。
- スリープよりスピンのほうが処理コストが低いためスピンする。スリープするとコンテキストスイッチが発生するので処理コストが高い。
- スリープ
- Timeout
- 一定時間経過するとOSが起こしてくれるようアラームをセットしてからスリープする。
- 最初は0.1秒スリープし、2回目以降は「前回スリープ時間 × 2」というアルゴリズムでスリープ時間が長くなっていく。
- スリープ時間は初期化パラメータ _MAX_EXPONENTIAL_SLEEP(8iではデフォルトで2秒) の値より大きくならない。
- ラッチを獲得しようとしているプロセスが既に他のラッチを獲得している場合は、初期化パラメータ _MAX_SLEEP_HOLDING_LATCH(8iではデフォルトで0.4秒) より大きくならない。
- Latch wait posting
- latch wait list というリストに自分を追加してからスリープする。
- ラッチを獲得しているプロセスがラッチを解放する時に latch wait list をチェックしてスリープしているプロセスを起こす。
- ラッチが解放され次第、待機しているプロセスがラッチを獲得できるが、latch wait list というデータ構造をメンテナンスするため処理コストが高い。
- デフォルトでは、Latch wait posting を使うのは library cache latches と shared pool latches のみ。
- Timeout
待機方法
- Willing-to-Wait Mode
- 獲得できなかった場合、待機して再要求する。
- No-Wait(Immediate) Mode
- プロセスが複数のラッチを同時に保持したい場合、同じまたは下位レベルのラッチを取得する際に使用する。
- 取得できなかった場合、上位レベルのラッチを解放してラッチの取得を再試行するか、エラーコードを返すか、他の処理を続行する。
クリーンアップ
チューニング
- 以下が最小になるようチューニングすると良いらしい。ただし、これをいじるのは最終手段。
_SPIN_COUNT * sleeps / misses
など