知識マップ: 共有メモリの落とし穴と実務ベストプラクティス

記事「共有メモリの落とし穴と実務ベストプラクティス」の主張を、概念と関係(エッジ)に分解した知識グラフの全体です。各関係には根拠・確認日・確度が付いています。

共有メモリはWindowsのCreateFileMapping/MapViewOfFileやPOSIXのshm_open/mmapを使い、同じ物理ページを複数プロセスから見せる仕組みだが、同期そのものではないため、同期なしで複数フィールドを読み書きするとwriterの書き込み途中を読んでしまう事故が起きうる。この事故はSPSCリングバッファやダブルバッファによるcommitプロトコルで防ぎ、生ポインタやHANDLEなどprocess-local資源はそのまま置けないためオフセット参照に置き換え、control planeとdata planeを分離して通知は別チャネルへ逃がすことが推奨される。加えて、ABIの固定、作成者だけが初期化する運用による初期化レースの回避、Windowsのabandoned mutexやPOSIXのrobust mutexを使ったクラッシュ復旧設計、名前空間・権限の構成、世代ごとのサイズ固定が、事故率を下げる実務上の要点になる。

共有メモリの落とし穴とベストプラクティスの知識マップ共有メモリがバイト列を共有するだけで同期そのものではないこと、途中状態の読み取りや初期化レース・クラッシュ復旧・ABI不一致・false sharingといった落とし穴、control planeとdata planeの分離やSPSCリングバッファ・ダブルバッファ・オフセット参照といった対策の関係を示す図利用する利用する利用する原因になり得る防止する防止する推奨される対応推奨される対応推奨される対応両立しない前提とする原因になり得る防止する推奨される対応利用する利用する原因になり得るで構成できる推奨される対応両立しない両立しない推奨される対応用いるのは非推奨利用する共有メモリCreateFileMapping/MapViewOfFileshm_open/ftruncate/mmapファイルマッピング(メモリマップトファイル)途中状態の読み取りSPSCリングバッファダブルバッファによるcommitプロトコルcontrol planeとdata planeの分離共有メモリの固定ヘッダオフセット参照process-localな資源共有メモリのABI設計初期化レースcreatorだけが初期化する運用クラッシュ復旧設計abandonedになったmutex(Windows)robust mutex(POSIX)false sharingとキャッシュライン競合名前空間と権限(Global/Local)世代ごとのサイズ固定運用他マシンとの共有通知を別チャネルへ逃がす設計busy loopによるポーリング通知名前付きパイプ

概念間の関係(全24件)

図と同じ関係を文章でも列挙します。表示している文と機械可読な意味データ(RDFa)は同じ要素に載っています。確度が「確立した関係」のものは直接の関係として、「条件付きの関係」のものは成立条件つきの言明(rdf:Statement)として表現しています。

主要概念の定義

共有メモリ
同じ物理ページを複数プロセスの仮想アドレス空間へマップし、同じバイト列を複数プロセスから見せる仕組み。同期そのものではない。
CreateFileMapping/MapViewOfFile
Windowsで名前付き共有メモリを作成・オープンし、プロセスのアドレス空間にマップするAPIの組み合わせ。pagefile-backedに使うとディスク非連携の共有メモリになる。
SPSCリングバッファ
producerがwrite_seqの位置へ書き、consumerがread_seqの位置から読む、writerとreaderがそれぞれ1つだけの固定長スロット配列。
ダブルバッファによるcommitプロトコル
非公開側バッファへ書き、長さやチェックサムを確定したうえでactive buffer indexを切り替え、readerは読み終えたあとにindexが変わっていないか再確認する公開手順。
control planeとdata planeの分離
開始・停止・エラーなどの制御はメッセージ系、フレームやバッチなどのデータ本体は共有メモリに置く設計方針。
共有メモリの固定ヘッダ
magic・abi_version・state・generation・heartbeatなどを先頭に置き、別物や未初期化・layout差異・初期化途中を検出できるようにする共有メモリのヘッダ設計。
オフセット参照
共有メモリ内の参照をポインタではなくセグメント先頭からの相対位置(offset)で持ち、各プロセスがbase + offsetで自分のアドレスに直す参照方式。
process-localな資源
生ポインタ、HANDLE、file descriptor、std::string、std::mutexなど、その値がプロセスの文脈にしか意味を持たない資源。
creatorだけが初期化する運用
共有メモリを作成した側だけが初期化を行い、あとから参加する側はREADY状態になるのを待つ運用ルール。
クラッシュ復旧設計
writerが共有データ更新中に落ちた場合に備えて、generation番号・最終commit済みsequence・heartbeat・dirty/cleanフラグ・破損時の全再初期化手順などを用意する設計。
世代ごとのサイズ固定運用
共有メモリのサイズをその世代では不変にし、拡張が必要なら新しいversion/name/generationのsegmentを作って参加者を切り替え、旧segmentを閉じる運用。
通知を別チャネルへ逃がす設計
readyフラグの共有メモリ上での表現に頼らず、event・semaphore・named pipeなど待てるprimitiveへ完了通知を分離する設計。
busy loopによるポーリング通知
共有メモリ上のreadyフラグをwhileループで見張り続けて通知を代替する実装パターン。

機械可読データ

このページはサイトの知識グラフ(_data/knowledge/)から自動生成されています。誤りの指摘はお問い合わせからお願いします。