process_flag(message_queue_data, Flag)について
process_flagのmessage_queue_dataについて調べていたら、Erlang Solutionsの記事に解説が載っていたのでさらっと読んでみた。
(上記のMessage Allocating Strategiesより)
バージョン19.0からprocess_flagにmessage_queue_dataなるフラグが追加されて、プロセスのメッセージキューについての設定できるようになった。
通常、プロセスが別プロセスにメッセージを送るときは以下のようなことが行われている。
- 送信されたメッセージの大きさの計算
- メッセージに対して十分の領域をアロケーション
- メッセージのペイロードをコピー
- メタデータを含めたメッセージコンテナーをアロケーション
- “受信プロセスのメッセージキュー”にメッセージコンテナを挿入
message_queue_dataのフラグは、ステップ2の送信者プロセスのアロケーションの戦略を決めることができるのと、メッセージのGCの取り扱われ方の制御を変更できる。
アロケーション戦略
Flagにはon_heap, off_heapがある。
on_heapの場合、プロセスの若いheapブロックにメッセージをアロケーションしようとする。さらに、この動作はプロセスのメインロックを取得する必要がある。ロックが取得できない場合はヒープのフラグメントが作成されて、その上にメッセージがコピーされる。
また、「ロックの競合が発生する可能性が高い = 他システムと強く共同して動作する」パターンらしく、この競合頻度が低い場合はon_heapの方が効率的と言える。逆に高いのであれば、off_heapとすることでメインロックの競合は殆どなくなる。その代わりに、ヒープフラグメントに割り当てる回数が増える。off_heapの場合、送信プロセスは常に送信するメッセージのヒープフラグメントを作成することになるため。
on_heapで若いヒープブロックに移動すると、GCで移動しなければならないデータ量が増える。大量のメッセージを受け取っている最中にGCが走ると、それらメッセージは若いヒープへと割り当てられていく。そして、メッセージはすぐに古いヒープへ昇格していく。大量のメッセージを受け取っている最中にGCが走れば、若いヒープサイズは大きくなり、古いヒープサイズも大きくなる。そうなると、GCに必要なメモリサイズも増える。メッセージがすべて消費された後、古いヒープに積まれているメッセージすべてをフルスイープGCすることになり時間がかかる。on_heap自体は他のモードよりも速い可能性が高いが、GCには時間がかかるのとメモリのコストが高いという特徴を知っておくと良さそう。
on_heapにするのかoff_heapにするのかは、プロセスが何をしているか、他のプロセスとどのように相互作用しているかに大きく依存している。なので、アプリケーションのプロファイルをとって、様々なパラメータで動作を確認してon_heapかoff_heapかを決定するべきだ。
