2016年7月22日金曜日

R: オブジェクトのサイズを考える

関数object.size()を使えば、オブジェクトのサイズを知ることができる。大きなデータを扱う場合、サイズは意識しておいた方が良いと思う。

とりあえず、character vectorをつくってサイズを眺めてみる。

# > x <- ""
# > nchar(x)
# [1] 0
# > object.size(x)
# 96 bytes

# > object.size("1")
# 96 bytes

# > object.size("1234567")
# 96 bytes

# > object.size("12345678")
# 104 bytes

# > object.size("123456789012345")
# 104 bytes

# > object.size("1234567890123456")
# 120 bytes

# > object.size("1234567890123456789012345678901")
# 120 bytes

# > object.size("12345678901234567890123456789012")
# 136 bytes

文字が長くなると表示しづらいので、for()で伸ばしてnchar()で文字数を確認し、object.size()で調査する。

# > x <- ""
# > for(i in 1:47) x <- paste(x, "a", sep = "")
# > nchar(x)
# [1] 47
# > object.size(x)
# 136 bytes

# > x <- ""
# > for(i in 1:48) x <- paste(x, "a", sep = "")
# > nchar(x)
# [1] 48
# > object.size(x)
# 152 bytes

# > x <- ""
# > for(i in 1:63) x <- paste(x, "a", sep = "")
# > nchar(x)
# [1] 63
# > object.size(x)
# 152 bytes

# > x <- ""
# > for(i in 1:64) x <- paste(x, "a", sep = "")
# > nchar(x)
# [1] 64
# > object.size(x)
# 216 bytes


文字の数とサイズは、どうやら以下の関係になっている。
0~7:   96 bytes
8~15:  104 bytes (+8)
16~31: 120 bytes (+16)
32~47: 136 bytes (+16)
48~63: 152 bytes (+16)
64~?:  216 bytes (+64)


一見すると秩序がありそう。
ということで、以下のコマンドでプロットしてみる。

main <- "Relationship between nchar and object.size"
sub <- c("64(blue), 128(green), 136(red), 144(orange)")
y <- ""
plot(x = nchar(y), y = object.size(y), 
   sub = sub, main = main, 
   xlim = c(0,550), ylim = c(0,700), pch = 20)
for(i in 1:550){
   y <- paste(y, "y", sep = "")
   points(x = nchar(y), y = object.size(y), pch = 20)
}
abline(v = c(64, 128, 136, 144), 
   col = c("blue", "green", "red", "orange"))



これはもう、本当に変なプロットになった。
どうやら、127文字を越えると取扱い方が変わるらしい。

# > x <- ""
# > for(i in 1:127) x <- paste(x, "a", sep = "")
# > nchar(x)
# [1] 127
# > object.size(x)
# 216 bytes

# > x <- ""
# > for(i in 1:128) x <- paste(x, "a", sep = "")
# > nchar(x)
# [1] 128
# > object.size(x)
# 224 bytes

# > x <- ""
# > for(i in 1:135) x <- paste(x, "a", sep = "")
# > nchar(x)
# [1] 135
# > object.size(x)
# 224 bytes

# > x <- ""
# > for(i in 1:136) x <- paste(x, "a", sep = "")
# > nchar(x)
# [1] 136
# > object.size(x)
# 232 bytes

# > x <- ""
# > for(i in 1:143) x <- paste(x, "a", sep = "")
# > nchar(x)
# [1] 143
# > object.size(x)
# 232 bytes

# > x <- ""
# > for(i in 1:144) x <- paste(x, "a", sep = "")
# > nchar(x)
# [1] 144
# > object.size(x)
# 240 bytes


まとめると、文字の数とサイズは以下の関係になっている。
0~7:      96 bytes
8~15:     104 bytes (+8)
16~31:    120 bytes (+16)
32~47:    136 bytes (+16)
48~63:    152 bytes (+16)
64~127:   216 bytes (+64)
128~135:  224 bytes (+8)
136~143:  232 bytes (+8)
144~152:  240 bytes (+8)
153~xxx:  8文字毎に8バイト増える。

基本的に1バイトに1文字が格納される計算になるのだが、そのオブジェクトの占有メモリは1文字毎に増えるのではない。あらかじめ決められた規則に則って、時には16文字分、あるいは64文字分のメモリが割り当てられる。しかも、どうやら128文字目以降は8文字単位でメモリの割り当てが増やされるらしい。

もうひとつの奇妙な現象を見つけた。
以下のコマンドを実行してもらうとわかるのだが、ひとつのベクターが2つの文字列をもち、しかもそれらの文字列が同一であれば、オブジェクトサイズは期待値よりも小さい。もしかしてfactorとして管理してるのかなぁ。

x <- ""
for(i in 1:10) x <- paste(x, "a", sep = "")
y <- c(x, x)
z <- c(x, paste(x, "b", sep = ""))
w <- c(paste(x, "b", sep = ""), paste(x, "b", sep = ""))
x
y
z
w
nchar(x)
nchar(y)
nchar(z)
nchar(w)
object.size(x)
object.size(y)
object.size(z)
object.size(w)

0 件のコメント:

コメントを投稿