golangにおけるcopy-on-write (COW)
結論
ない?!と思った
検証
雑にこんなコードがある
package main import ( "fmt" "runtime" ) var mem runtime.MemStats func printMem() { runtime.ReadMemStats(&mem) fmt.Printf("%d byte \n", mem.Alloc) } func main() { v := [9999999]int{} var i int for i = 0; i < 9999999; i++ { v[i] = i } printMem() c := v printMem() fmt.Println(v[0]) fmt.Println(c[0]) }
実行すると
- go run test.go 80,115,344 byte 160,122,064 byte
すでに変数に代入した段階で実際に値がコピーされている為に利用メモリが増えている
例えばcopy-on-write (COW)の最適化が働いている場合は
例えばPHPとかで同じように下記のテストコードがある
<?php $a = array_fill(0, 999, "aaa"); echo number_format(memory_get_usage()) . "byte \n"; $b = $a; // 配列を代入 echo number_format(memory_get_usage()) . "byte \n";
実行すると
- php test.php 323,960byte 324,096byte
誤差は多少あれど、変数に代入しただけでは利用メモリは増えない。
今度は変数に代入した先で値を変えて(writeを発生)やる
<?php $a = array_fill(0, 999, "aaa"); echo number_format(memory_get_usage()) . "byte \n"; $b = $a; // 配列を代入 echo number_format(memory_get_usage()) . "byte \n"; $b[1] = 0; // 代入先の配列を変更 echo number_format(memory_get_usage()) . "byte \n";
実行すると
- php test.php 324,536byte 324,672byte 421,000byte
writeが発生したため、実際に値のコピーをしてからwriteした為、メモリ利用量は増えた。
なので
golangにおいてはcopy-on-writeで裏で最適化してくれはしないようですね。なんとなく頭に入れながらコーディングをしていこうかと思います。
なんでないのだろうか?とか、もっと別の理由であえてないとか、深堀してみたいけど帰ってこれなくなりそうなので一旦ここまでにしとこうかと思う