ablog

不器用で落着きのない技術者のメモ

Xen の xen_blkfront.max とはなんぞや

※以下は個人的なメモです。最新の正確な情報はAWSの公式ドキュメントなどを参照してください。

疑問点

EC2 のドキュメントで xen_blkfront.max=256 が推奨されているが、このパラメータは何を意味するのか?

4.2 以降のすべての Linux カーネルの場合、st1 ボリュームまたは sc1 ボリュームで最大スループットを得るには、xen_blkfront.max パラメータを 256 に設定することをお勧めします。このパラメータは、OS の起動コマンドラインで設定できます。たとえば、Amazon Linux AMI では、/boot/grub/menu.lst に記述されている GRUB 設定で kernel 行の末尾に追加できます。

Linux インスタンスの Amazon EBS ボリュームのパフォーマンス - Amazon Elastic Compute Cloud

調査結果

  • Xen ではゲストとドライバドメイン間でのI/Oデータは共有メモリページ(1ページ=4KB)を介してやり取りする。
  • リングにI/Oリクエスト構造体が格納され、そのうち Segment にデータの実体が格納されていた。
  • Linux Kernel 3.11 以降、VirtIO protocol にインスパイアされて "Xen indirect descriptors implementation" では Segment にデータの実体を持つのではなく共有メモリページへのポインタにする事でリングで管理可能な共有メモリページが大きくなった。
  • 結果、同時にI/O可能なデータ量が1.4MBから512MBに上がった(xen_blkfront.max=256に設定した場合)。
  • I/Oリクエストあたりの最大セグメント数は xen_blkfront.max で指定でき、デフォルト 32、最大 256。
  • ゲストとドライバドメインの両方のバージョンの3.11以上でないと使えない。
  • Before: 1.4MB = 44KB(4KB * 11) * 32
struct blkif_request {
	uint8_t        operation;
	uint8_t        nr_segments;
	blkif_vdev_t   handle;
	uint64_t       id;
	blkif_sector_t sector_number;
	struct blkif_request_segment {
		grant_ref_t gref;
		uint8_t     first_sect, last_sect;
	} seg[11]; ★
};
  • After: 512MB = 16MB (4KB * 4096) * 32
struct blkif_request_indirect {
	uint8_t        operation;
	uint8_t        indirect_op;
	uint16_t       nr_segments;
	uint64_t       id;
	blkif_sector_t sector_number;
	blkif_vdev_t   handle;
	uint16_t       _pad2;
	grant_ref_t    indirect_grefs[8];
};

struct blkif_request_segment_aligned {
	grant_ref_t gref;
	uint8_t     first_sect, last_sect;
	uint16_t    _pad;
};