2013-10-23 93 views
3

確定除object.size以外的對象大小(或使其更快執行的方法)是否存在更快速的方法?快速替代object.size?

start.time <- Sys.time() 
object.size(DB.raw) 
# 5361302280 bytes 
Sys.time() - start.time 
# Time difference of 1.644485 mins <~~~ A minute and a half simply 
              to show the size 

print.dims(DB.raw) 
# 43,581,894 rows X 15 cols 

我想知道爲什麼需要這麼長的時間來計算對象大小?推測每個列都必須遍歷每一行才能找到該列的總大小?

+0

'system(「ls -l DB.raw」)'? (是的,我知道這件事目前在你的環境中,而不一定是一個文件)。如果你嘗試類似'object.size(unlist(DB.raw))',它有幫助嗎?還是僅僅採用'prod(dim(DB.raw))* {每個元素的字節數}'可以接受? –

+0

卡爾,'unlist'選項(使用'use.names = FALSE')在10分鐘以上,仍然在繼續,所以我猜不是,但是很好的建議。 '系統',因爲你提到,在這種情況下不是一個選項 –

+1

嗯,我只有8GB的機器。 'DB.raw'已經是5 + GB了。如果我'unlist'它,然後我的可憐的小電腦開始咳嗽 –

回答

6

在Windows盒子上,在創建DB.raw之前和之後,您可以使用gc()memory.size()獲得相當接近的估計值。

gc() 
x <- memory.size() 
# DB.raw created, extra variables rm'ed 
gc() 
memory.size() - x # estimate of DB.raw size in Mb 
# object.size(DB.raw)/1048576 # for comparison 
+1

不幸...'警告消息: 「memory.size()」是Windows的特定 ' –

+0

無賴。我將在此留下答案,以防止Windows用戶遇到類似情況。 –

+0

絕對是。 +1一個好主意 –

2

它需要很長時間的最可能的原因是因爲你有角色對象。這似乎是因爲它需要計算字符的數量才能確定大小,儘管我不確定。

x<-rep(paste0(letters[1:3],collapse=""),1e8) 
system.time(object.size(x)) 
## user system elapsed 
## 1.608 0.592 2.202 
x<-rep(0.5,1e9) 
system.time(object.size(x)) 
## user system elapsed 
## 0.000 0.000 0.001 

我們可以看到更長的字符串佔用了更多的空間(至少在某些情況下)是這樣的:

> x<-replicate(1e5,paste0(letters[sample(26,3)],collapse="")) 
> x1<-replicate(1e5,paste0(letters[sample(26,2)],collapse="")) 
> object.size(x) 
1547544 bytes 
> object.size(x1) 
831240 bytes 

我想不出解決這個辦法,如果你需要的確切尺寸。但是,您可以通過抽樣大量行並對示例調用object.size()來獲得對每行大小的估計值,然後乘以所擁有的總行數,從而得到高度準確的大小估計值。

例如:

estObjectSize<-function(x,n=1e5){ 
    length(x)*object.size(sample(x,n))/n 
} 
x0<-sapply(1:20,function(x) paste0(letters[1:x],collapse="")) 
x<-x0[sample(20,1e8,T)] 

> system.time(size<-object.size(x)) 
    user system elapsed 
    1.632 0.856 2.495 
> system.time(estSize<-estObjectSize(x)) 
    user system elapsed 
    0.012 0.000 0.013 
> size 
800001184 bytes 
> estSize 
801184000 bytes 

你必須調整代碼一點得到它爲數據幀的工作,但是這是想法。

要添加:它看起來像每個字符存儲字符串數組的字節數取決於一些因素,包括串實習和字符串施工過程中使用過量的分配的緩衝存儲器中。它當然不如乘以字符串數量那麼簡單,並且它應該花費更長的時間並不奇怪:

> bytesPerString<-sapply(1:20, 
+ function(x) 
+  object.size(replicate(1e5,paste0(letters[sample(26,x)],collapse="")))/1e5) 
> bytesPerString 
[1] 8.01288 8.31240 15.47928 49.87848 55.71144 55.98552 55.99848 64.00040 
[9] 64.00040 64.00040 64.00040 64.00040 64.00040 64.00040 64.00040 80.00040 
[17] 80.00040 80.00040 80.00040 80.00040 
> bytesPerChar<-(bytesPerString-8)/(1:20+1) 
> bytesPerChar 
[1] 0.0064400 0.1041333 1.8698200 8.3756960 7.9519067 6.8550743 5.9998100 
[8] 6.2222667 5.6000400 5.0909455 4.6667000 4.3077231 4.0000286 3.7333600 
[15] 3.5000250 4.2353176 4.0000222 3.7894947 3.6000200 3.4285905 
+0

我想說的是(正如你發現的那樣),我懷疑這是錯誤的字符列。我試圖測量的部分是通過轉換來自不同類的列來丟失/獲得多少內存,並且顯示對象大小几乎需要幾乎同時進行不同的轉換。 –

+1

好吧,字符確實需要比數字類型更長的時間。看我最近的編輯。它看起來在某些情況下,字符串長度確實會影響字符對象的大小。我想知道當計算這樣的大小時,R是否試圖跟蹤哪些字符串實際上是指向相同字符數組的指針。 – mrip

+0

@mrip是的,R有一個全局字符串池,所以計算向量的大小很困難,因爲它必須確定它有多少個唯一標識符。比較'object.size(「banana」)''object.size(rep(「banana」,1e6))/ 1e6' – hadley