2015-04-17 30 views
8

我讀哈德利的預研編程和但在討論時的內存大小人物也這樣說:R中字符的對象大小 - R全局字符串池如何工作?

R有一個全球性的字符串池。這意味着每個唯一的字符串只存儲在一個地方 ,因此字符向量佔用的內存比您預期的要少。

書中給出的例子是這樣的:

library(pryr) 
object_size("banana") 
#> 96 B 
object_size(rep("banana", 10)) 
#> 216 B 

一個本節中的練習是這兩個特徵向量比較:

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 

現在,由於通道指出R有一個全局字符串池,並且由於矢量vec主要由兩個字符串(「ba」和「na」)的重複組成,所以實際上我會 - 直觀地 - 期望vec的大小小於尺寸爲str

所以我的問題是:你怎麼能最準確地估計這些載體的大小事先?

+0

這只是想大聲,但我敢打賭,這取決於實例化向量之前的字符串池的大小。你做過任何實驗來測試矢量的長度,該矢量中字符串的(累積)長度,以及某些或所有字符串是否在字符串池中被讀取(即x < - 'foo ',y = c('foo','bar'))等等?另外,這可能與平臺有關,因爲我得到的對象大小完全不同:前面說過,'object_size(vec)'產生'7.42 kB'和'object_size(str)'產生'6.89 kB'。 – Jthorpe

回答

1

關鍵的區別是因爲vec中的指針:每個短標量字符串(CHARSXP)必須從相應的字符串向量(STRSXP)中指向。你在vec裏面有一些1326這樣的字符串指針,但在str裏只有51(指針可能是你平臺上的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