2017-10-14 66 views
1

我是新來的,如果我的問題已經被回答,提前抱歉,但我現在搜索了幾天,發現沒有解決方案或解釋呢。Excel VBA - 填充Variant數組增加內存使用量

問題是,在一個變種陣列的人口中,內存消耗不斷增加。該陣列的尺寸是,並且當它是第一個尺寸時,我可以看到內存消耗如何增加相應的量。我認爲,一小塊的代碼將更好地解釋它比文字:

Sub test() 
Dim Arr(1 To 1000000, 1 To 10) As Variant 
Dim i As Long, j As Integer 

For i = 1 To 1000000 
    For j = 1 To 10 
     Arr(i, j) = "AAAAAAAAA" 
    Next j 

Next i 

End Sub 

我這段代碼的經驗是 - 陣列標註內存利弊之後。增加約。 160 MB(即10 * 1 000 000 * 16)。執行完成後,我已經增加了大約400 MB!有趣的是 - 如果用一個數字替換字符串AAAA,這個問題就消失了。

在實際的程序(這只是一個測試代碼)我有一個更大的數組約。 600 MB,但在代碼執行結束時,內存使用量爲3.4 GB!結果是「內存不足」錯誤。

任何人都可以解釋一下嗎?

由於提前, 書齋

+0

爲什麼你覺得奇怪的是,當你把一個數組中的字符串,用來存儲該數組的內存增加?字符串本身不存儲在變量變量的內存中。無論如何,Excel VBA可能是這種規模數據的錯誤工具。也許使用像R這樣的東西(如果你想保留某個前端,可以與Excel進行交互)可能是一個很好的戰略舉措。 –

+0

以下內容可能會幫助您理解爲什麼使用大型變體陣列來存儲大量字符串會使用如此多的內存:http://bytecomb.com/vba-internals-whats-in-a-variable/ –

+0

我很善良必須爲這項任務而努力。我沒有預料到內存消耗會增長,因爲我聲明瞭這個數組,所以我期待它會保留必要的內存,這是16字節,用於不同時間的列時間行,在這種情況下是160 MB,我可以在聲明數組時,請參閱任務管理器中的+160 MB。但是在執行期間,內存使用量會增加,直到我有另外的400 Mb,那麼對於那個數組大小,總共660 Mb?當爲陣列填充雙打時,爲什麼內存消耗不會增加?我看到了提議的主題,但我會閱讀的鏈接,謝謝。 – Den

回答

2

你們看到的是,當一個變種包含字符串,實際的字符串數據沒有在內部存儲的事實引起的。一個變體由16個字節組成。這16個字節的佈局描述如下here。請注意,這些字節中的8個包含類型信息之類的內容,其他8個包含實際數據,該數據爲數字。當數據是字符串時,這8個字節是不夠的。相反,這8個字節包含一個指向BSTR結構的指針,該結構由4個字節組成,其中包含一個字符串長度,字符串中的實際字符(每個字符2個字節)和一個2個字符的空終止符。對於長度爲9的字符串,可以計算出24個字節,因此總共需要16 + 24 = 40個字節來存儲該字符串(以及它指向的變體)。這就解釋了爲什麼當你以這種方式存儲這1000萬個字符串時,至少需要400 MB的空間。

正如你所看到的,變種是一個記憶豬。如果你真的需要使用Excel VBA來做這件事,你應該避免像鼠疫這樣的變種陣列。字符串本身效率不高。也許你可以做一些事情,比如將字符的ascii代碼存儲爲字節,或者將許多字符串合併成一個可以在需要時拆分的字符串。

+0

John,非常感謝您提供了一個簡單明瞭的解釋!它現在有很多意義。我基本上知道變體是不好的,效率低下的,但我不知道它們太糟糕了。我的數據實際上主要是數字,它只包含數據列的標題。在這種情況下使用變體只是比較簡單,其中一個原因是我通過將文本文件讀爲二進制數據來獲取數據,以便獲取一個字符串,並將其分割並寫入變體數組。但是,由於它造成了問題,我想我將不得不使用一個小的字符串數組作爲標題和一個單獨的雙數組作爲數據。 – Den