目的
これから導入・実装する技術や概念について、前提知識・関連知識を収集・整理し、ユーザーの理解を促します。
- •これから導入する技術について「それは何か」「なぜ使うのか」「どう使うのか」を理解する
- •専門用語や前提知識を先回りして解説する
- •因果関係を明確にし、「なぜそれが必要か」の根拠を示す
手順
疑問を列挙 → その答えを調査・整理 → 新たな疑問を列挙 → その答えを調査・整理 → ... を繰り返し、実装に着手可能なレベルまで掘り下げます。
出力は、「連想ツリーの出力例」セクションと同じフォーマットで出力してください。
以下は、出力フォーマットをメタ的に表現したものです。
code
- {疑問}
- {その答え}
- {補足情報}
- {補足情報}
- {新たな疑問}
- {その答え}
- {新たな疑問}
- {その答え}
- {新たな疑問}
- {その答え}
- {補足情報}
- ...
- {新たな疑問}
- {その答え}
- {その答え2}
- ...
- ...
連想ツリーを広げるためのヒント
- •タスクや回答文に、キーワードとなる技術・ツール・概念はあるか?
- •What(それは何か?)・Why(なぜ使うのか?)・How(どう使うのか?)
- •現在のリポジトリや社内に前例はあるか?
- •具体例は?
- •前提・依存はあるか?
- •比較対象はあるか?
- •抽象的、もしくは具体的にはどういうことか?
答えを調査・整理する際のポイント
- •
因果関係を明確にする
- •「〜が必要」と述べる場合、必ず「なぜ必要か」の根拠を示す
- •悪い例
code
- PitchforkはReforkingによりメモリ効率が改善する
- •良い例
code
- Rubyアプリケーションはリクエスト処理によってメモリを遅延ロードする - 初期化時のforkでは、まだロードされていないメモリが多い - リクエスト処理後にメモリへの書き込みが発生すると、Copy-on-Writeが働き、メモリが各プロセスに複製される - よって、初期化時のforkではCoW効率が時間とともに低下する - Reforkingでは、既に「温まった」ワーカーからforkするため、共有メモリが増える - 結果として、メモリ使用量が約30%削減される
- •
5W1Hを意識した文章で説明する
- •悪い例:
id: を送ると Last Event ID が更新される - •良い例:
サーバーがid:を送ると、クライアントは最後に受け取ったイベントIDを保持し、接続が切れた後に再接続するときはLast-Event-IDヘッダーとして送る
- •悪い例:
- •
マーク(例:
理由:,推測:)などは使わず、文章で説明する
連想ツリーの出力例
「今はunicornを使っているけれど、pumaと比較した上でpitchforkの方がよければ乗り換えたい」 というタスクを例に、連想ツリーの例を示します。
与えられたタスクについて答える際も、以下のような思考を辿り、以下のようなフォーマットで出力してください。
code
- unicorn、puma、pitchforkとは何か?
- いずれもRubyのアプリケーションサーバー
- Unicornはマルチプロセス
- マルチプロセスの利点は?
- プロセス間でメモリが分離されるため、1つのクラッシュが他に波及しにくい
- スレッドセーフでないコードでも動かしやすい
- どんなコードがスレッドセーフでないのか?
- グローバル変数やクラス変数に書き込みをする処理
- 外部ライブラリが内部で共有状態を持つ処理
- マルチプロセスの欠点は?
- プロセスごとにメモリを持つため総メモリが増えやすい
- どの程度増えるのか?
- ワーカー数に比例してベースメモリが増える傾向がある
- Pumaはマルチスレッド+マルチプロセス
- なぜマルチスレッドを使うのか?
- I/O待ち中に他のリクエストを処理でき、スループットが向上しやすい
- どの処理がI/O待ちになりやすい?
- DBアクセスや外部API通信、ファイル読み書き
- マルチスレッドの注意点は?
- 同時アクセスでデータ競合が起きる可能性がある
- 具体的にどんな競合が起きる?
- 共有変数の更新順序が不定になり、結果が壊れる
- キャッシュやメモ化が意図通りに動かない
- PitchforkはUnicorn由来でReforkingが特徴
- Reforkingの詳細な仕組みは?なぜメモリ効率が改善するのか?
- 一定リクエスト処理後の温まったワーカーをテンプレートとして再forkし、Copy-on-Writeの共有を増やす仕組み
- どうして温まったワーカーが有利なのか?
- 遅延ロードされたコードやデータがメモリに載るため共有できる領域が増える
- その結果、プロセス間で同じメモリを共有しやすくなる
- それぞれの違いは?
- Unicornはマルチプロセス
- Pumaはマルチスレッド+マルチプロセス
- Pitchforkはマルチプロセス+Reforking
- 違いは運用にどう影響する?
- Pumaはスレッドセーフ性の検証が必須
- Unicorn/Pitchforkはスレッドセーフ性の負担が小さい
- その代わり何が必要?
- メモリ使用量の監視とプロセス数の調整
- なぜ乗り換えを検討するのか?
- メモリ削減やパフォーマンス改善が期待できる
- 具体的な効果はどう測る?
- メモリ使用量とレイテンシーを移行前後で比較する
- どんな指標を使う?
- RSSやワーカー単位のメモリ、p95/p99レイテンシー
- Rails新バージョンや運用要件に合わせたい
- どんな運用要件が影響する?
- コンテナ運用、デプロイ頻度、障害時の復旧時間
- それぞれどう影響する?
- コンテナはメモリ制限が強い
- デプロイ頻度が高いと再起動のコストが増える
- どのような基準で選ぶべきか?
- スレッドセーフ性
- どう判断する?
- 主要gemとアプリコードのスレッドセーフ性を洗い出す
- どこを見ればいい?
- gemのREADMEやissue、社内での利用実績
- I/O待ちの多さ
- どう判断する?
- APMやログで外部依存の待ち時間を確認する
- 待ちが多いと何が有利?
- Pumaのマルチスレッドで待ち時間を隠蔽できる
- メモリ制約
- どう判断する?
- 本番環境のメモリ上限と現状の使用量を比較する
- 余裕がない場合は?
- PitchforkのReforkingでメモリ削減を狙う
- 乗り換えのデメリットや注意点は?
- Pumaへの移行
- スレッドセーフ性の担保が必要
- どんな対応が必要?
- 共有状態の排除やローカル変数化、mutexの導入
- Pitchforkへの移行
- フォークセーフ性の検証が必要
- フォークセーフでないと何が起きる?
- ソケットやDB接続が壊れ、リクエスト失敗が増える
- それを避けるには?
- fork後に接続を再確立する設定が必要
- どのように移行するのか?
- Gemfileの変更
- 具体的には?
- 対象サーバーのgemを追加し、既存のサーバーgemを外す
- 設定ファイルの移行
- どこが変わる?
- Unicornの設定をPumaやPitchforkの設定形式に合わせる
- 変換の難所は?
- ワーカー数、タイムアウト、フックの対応付け
- 段階的ロールアウト
- どうやる?
- 一部トラフィックのみ新サーバーで受け、問題がないか観測する
- 何を観測する?
- エラー率、レイテンシー、メモリ使用量