犯行動機、かく語れり
D言語の配列が付け足し等によって、どのように延長されるのか?を試してみました。
配列を接続した際、メモリがどれだけ慌ただしく動くのか?を知っておきたかったんです。
検証
内容は至って簡単。
- byte型動的配列(buffer)に1要素(=1バイト)ずつ足していく。
- 配列の先頭アドレス(buffer.ptr)からメモリブロック情報(BlkAttr)を、GC.query関数で取り出す。
- 確保先頭アドレスとその長さが変わったら、標準出力。
- 出力結果をじっくりたっぷりねぶりあげるように観察。
テストコードは以下のとおり。
import
core.memory ,
std.stdio ;
void main()
{
byte[] buffer;
void* base = GC.query(buffer.ptr).base;
size_t size = GC.query(buffer.ptr).size;
writefln( "length=% 8d, ptr=xxxxxxxx -> %08X, length=% 8d",
buffer.length,
base,
size
);
foreach( i ; 0 .. 1024*1024 ){
buffer ~= 0;
auto bi = GC.query(buffer.ptr);
if( base != bi.base || size != bi.size ){
writefln( "length=% 8d, ptr=%08X -> %08X, length=% 8d(% +8d)",
buffer.length,
base,
bi.base,
bi.size,
bi.size - size
);
base = bi.base;
size = bi.size;
}
}
}
結果
output:
length= 0, ptr=xxxxxxxx -> null, length= 0
length= 1, ptr=null -> 009D1FE0, length= 16( +16)
length= 16, ptr=009D1FE0 -> 009D2FE0, length= 32( +16)
length= 32, ptr=009D2FE0 -> 009D3FC0, length= 64( +32)
length= 64, ptr=009D3FC0 -> 009D0F00, length= 128( +64)
length= 128, ptr=009D0F00 -> 009D4F00, length= 256( +128)
length= 256, ptr=009D4F00 -> 009D5E00, length= 512( +256)
length= 511, ptr=009D5E00 -> 009D6C00, length= 1024( +512)
length= 1023, ptr=009D6C00 -> 009D7800, length= 2048( +1024)
length= 2047, ptr=009D7800 -> 00BD0000, length= 4096( +2048)
length= 4080, ptr=00BD0000 -> 00BD0000, length= 8192( +4096)
length= 8176, ptr=00BD0000 -> 00BD0000, length= 16384( +8192)
length= 16368, ptr=00BD0000 -> 00BD0000, length= 28672( +12288)
length= 28656, ptr=00BD0000 -> 00BD0000, length= 49152( +20480)
length= 49136, ptr=00BD0000 -> 00BD0000, length= 65536( +16384)
length= 65520, ptr=00BD0000 -> 00BD0000, length= 69632( +4096)
length= 69616, ptr=00BD0000 -> 00BD0000, length= 110592( +40960)
length= 110576, ptr=00BD0000 -> 00BD0000, length= 131072( +20480)
length= 131056, ptr=00BD0000 -> 00BD0000, length= 135168( +4096)
length= 135152, ptr=00BD0000 -> 00BD0000, length= 212992( +77824)
length= 212976, ptr=00BD0000 -> 00BD0000, length= 262144( +49152)
length= 262128, ptr=00BD0000 -> 00BD0000, length= 266240( +4096)
length= 266224, ptr=00BD0000 -> 00BD0000, length= 405504( +139264)
length= 405488, ptr=00BD0000 -> 00BD0000, length= 458752( +53248)
length= 458736, ptr=00BD0000 -> 00BD0000, length= 462848( +4096)
length= 462832, ptr=00BD0000 -> 00BD0000, length= 704512( +241664)
length= 704496, ptr=00BD0000 -> 00BD0000, length= 720896( +16384)
length= 720880, ptr=00BD0000 -> 00CD0000, length= 1081344( +360448)
推察(ソースを見ずに)
- アロケーション領域をその場から伸張できる場合、伸ばす(自動で伸ばす長さに法則性が見出だせず)。
- 伸張できない場合、再確保+配列コピーを実施。
まだ調べたいこと
マルチスレッド環境下でのアロケーション性能とかも気になる所。とはいえ、実行速度にセンシティブな運用(ゲームユースとか)だと、アロケーション系命令の実行機会最小化を目指す工夫が必要かも。