2011-12-13 61 views
11

公認的觀點是使用像Dim dict As New Dictionary這樣的結構在性能上比Dim dict As Dictionary/Set dict = New Dictionary差。Excel VBA自動實例化的神話性能不佳嗎?

解釋是前面的示例 - 自動實例化 - 將實例化延遲到變量dict的第一次使用。因此,每次字典被引用,編譯的代碼必須首先檢查dict是否等於Nothing。

但是,我發現編譯代碼無論如何都這樣做。每當您嘗試使用Nothing的對象引用時,您都會收到錯誤消息。

所以,爲了向科學致敬,我跑了一些測試。結果表明兩種方法之間沒有性能差異。 (在Excel 2007上運行)

調用「創建字典&添加2個項目」100,000次。

  • 明確:16,891ms /自動:16,797ms(自動94ms更快)
  • 明確:16,797ms /自動:16,781ms(自動爲16ms更快)

反向測試調用的順序:

  • 自動:16,766ms /顯式:16,812ms(自動46ms更快)
  • 自動:16,828ms /顯式:16,813ms(顯式15ms的更快)

調用「創建字典&添加6個項目」100,000次。

  • 汽車:17,437ms /明確:17,407ms(顯式30毫秒更快)
  • 汽車:17,343ms /明確:17,360ms(自動17MS更快)

創建詞典並添加100000項目。

  • 汽車:391ms /明確:391ms(同)

創建詞典並添加百萬個。

  • 汽車:57,609ms /明確:58,172ms(自動563ms更快)
  • 明確:57,343ms /自動:57,422ms(顯式79ms更快)

我看到任何跡象表明自動實例化與顯式實例化的關係很差。 (要清楚,由於其他原因,我會避免自動實例化,但我只是在這裏表現角度感興趣。)

那麼這是一個神話嗎?

UPDATE

讓我奠定了爲什麼性能說法沒有道理給我。據說,

x.Add("Key", "Item") 
在自動實例化對象

等同於以下內容:

If x is Nothing then 
    Set x = New Dictionary 
End If 
x.Add("Key", "Item") 

這使得它看起來像「可怕的開銷,」如果你調用這個數千次。但是在顯式實例的情況下,它在代碼的編譯版本生成邏輯的完全形式:

If x is Nothing Then 
    Err.Raise "Object variable not set..." 
End If 
x.Add("Key", "Item") 

這並不一定意味着汽車是更長的時間,這就是爲什麼我問是否有任何事實。我想知道我是否已經確定了許多未經考驗的表演神話中的另一個。

+0

它確實只是不同的「Nothing」語義,它將'As New'設置爲與Dim/Set'略有區別。正如你所說的,涉及運行時類型檢查的所謂開銷是不相關的,除非檢查的自動實例化對象實際上*是*'Nothing',否則不會發生比如果它是Dim/Set引用更多的情況。 –

+0

@Alex K,這個古老的性能指南說*每個*變量的引用都會在自動情況下調用一個「If X Is Nothing」檢查,而Dim/Set變量不會。所以當你在聲明後訪問對象時,你必須測試是否有性能問題,而不是測試聲明本身。 –

+0

@JP不是真的 - 我在今天看到的另一個SO問題後Google搜索了一下。例如:http://www.cpearson.com/excel/classes.aspx另一個例子:http://www.bettersolutions.com/vba/VUA113/LI912711911.htm –

回答

5

我知道如果沒關係,或者不要暗淡爲新,那麼就有神聖的方式,但我從來沒有聽說過它會導致糟糕的表現。 簡短的回答是不是真的。是的,它通過粗略的檢查來清理你的代碼,看看它不是什麼,但是你不會注意到由於今天的機器而產生的速度差異。這就像是說「循環超過10000個字符比10001快。要開始看到任何區別,你需要循環你的測試,以更高的數字,如數百萬和數千萬。」

這就是說暗淡新爲皺眉在而不是性能的原因。

  • 您失去控制時,它的初始化
  • 你輸了,檢查的對象是沒有
  • 速度差或沒有能力的能力,但它確實垃圾你的代碼非正式檢查

授予如果您只是使用VBA來自動化一些工作表的東西或操縱數據,您可能不會在意這些,但是當您看到更復雜的代碼時,失去了測試對象是否爲Nothing的能力以及不控制何時初始化是巨大的,並可能產生意想不到的行爲,更不用說讓測試成爲一種痛苦的屁股。所有這些用於保存幾行代碼。

然後有一些微優化器會爭辯說,向代碼中添加任何不需要的東西都會導致性能下降。雖然他們在某些方面是正確的,但在這種情況下,您最可能節省0.000000001秒。

+0

我同意你失去控制它初始化的能力;我認爲這是一個更嚴重的問題,將對象設置爲Nothing幾乎是不可能的。但問題是關於「不必要的檢查」 - 這是真的嗎?畢竟,如果我把Dim x寫成字典,那麼x.Add(1,「m」) - 我會得到一個錯誤,「Object variable not set」意味着編譯的VBA無論如何都會檢查它。 –

+0

在編譯期間檢查和在運行時檢查是非常不同的。相信我,在編譯時檢查是一件好事,讓它運行時不是。 :)當一個錯誤被拋出時,並不是因爲它被檢查並意識到它不能這樣做,而是因爲它試圖做一些它無法做到的事情。 – aevanko

+0

+1「失去測試對象是否爲Nothing並且在初始化時不控制的能力」 - 程序員應該掌握控制權,而不是代碼。當聲明一個變量時沒有隱含的「沒有什麼」檢查會帶來的性能好處遠遠超過了這個考慮因素。 – JimmyPena