【r<-探索】对象大小——R存储真的会占很大空间吗?

R存储真的会占很大空间吗?本文通过一些简单的示例带你接近真相。

我们利用lobstr::obj_size()函数访问对象的大小。

obj_size(letters)
#> 1,712 B
obj_size(ggplot2::diamonds)
#> 3,456,344 B

在上一篇文章中介绍过列表存储的不是实际的值,而是指向值的引用,所以一个列表的大小比我们预期的可能要小的多。

x <- runif(1e6)
obj_size(x)
#> 8,000,048 B

y <- list(x, x, x)
obj_size(y)
#> 8,000,128 B

这里变量y仅比变量x大80个字节!这正是有3个空值的列表大小:

obj_size(list(NULL, NULL, NULL))
#> 80 B

相似地,R采用全局字符串池,所以字符串向量占用的内存比我们想象中要小的多,重复一个字符串1万次并不会占用相应1万倍的存储空间。

banana <- "bananas bananas bananas"
obj_size(banana)
#> 136 B
obj_size(rep(banana, 100))
#> 928 B

因为引用的使用,估计独立变量占用的内存将比较有挑战性。除非变量x和变量y没有共享元素,obj_size(x) + obj_size(y) = obj_size(x, y)才会成立。

obj_size(x, y)
#> 8,000,128 B

最后,R v3.5.0版本开始引入了ALTREP, short for alternative representation,以:符号指定的序列将不会记录所有的数值,而是记录这个序列,这让它所占用的内存更小了。下面的结果显示无论序列多大啊,占用的内存都是一样的!

obj_size(1:3)
#> 680 B
obj_size(1:1e3)
#> 680 B
obj_size(1:1e6)
#> 680 B
obj_size(1:1e9)
#> 680 B

不止我们在进步,编程语言也在进步喔!


内容整理自Advanced R。