R中字符的对象大小 - R全局字符串池如何工作?

Car*_*lli 9 memory r vector character

我正在阅读Hadley的高级R编程,当它讨论字符的内存大小时,它说:

R有一个全局字符串池.这意味着每个唯一字符串仅存储在一个位置,因此字符向量占用的内存比您预期的要少.

本书给出的例子如下:

library(pryr)
object_size("banana")
#> 96 B
object_size(rep("banana", 10))
#> 216 B
Run Code Online (Sandbox Code Playgroud)

本节中的一个练习是比较这两个字符向量:

vec <- lapply(0:50, function(i) c("ba", rep("na", i)))
str <- lapply(vec, paste0, collapse = "")

object_size(vec)
13.4 kB

object_size(str)
8.74 kB
Run Code Online (Sandbox Code Playgroud)

现在,由于该段落声明R具有全局字符串池,并且由于向量vec主要由两个字符串("ba"和"na")的重复组成,所以我实际上 - 直觉地 - 期望大小vec小于大小的str.

所以我的问题是:你怎么能最准确地预先估计这些矢量的大小?

Tom*_*era 3

主要区别在于 中的指针vec:每个短标量字符串 (CHARSXP) 都必须从相应的字符串向量 (STRSXP) 指向。里面有大约 1326 个这样的字符串指针vec,但 in 中只有 51 个str(在你的平台上一个指针可能是 8 个字节)。该池用于标量字符串(也称为 CHARSXP 缓存)。另一个不明显的因素是内部碎片,例如在我的系统上,标量字符串无论是否有 0 到 7 个字符都采用相同的大小,8 个字符的字符串只需要更多,等等。请参阅以下重复尺寸:

unlist(sapply(str, object.size))

[1] 96 96 96 104 104 104 104 120 120 120 120 120 120 120 120 136 136 136 136

[20] 136 136 136 136 152 152 152 152 152 152 152 152 216 216 216 216 216 216 216

[39] 216 216 216 216 216 216 216 216 216 216 216 216 216

然而,这些是 R 内存管理器的实现细节,可能会发生变化,并且不应在用户程序中以任何方式依赖它们 - 使用另一种对象布局/内存管理器,str可能会使用比vec.