2010-04-22 90 views
2

考慮以下代碼:爲什麼速度不同?

function Foo(ds as OtherDLL.BaseObj) 
    dim lngRowIndex as long 
    dim lngColIndex as long 

    for lngRowIndex = 1 to ubound(ds.Data, 2) 
     for lngColIndex = 1 to ds.Columns.Count 
      Debug.Print ds.Data(lngRowIndex, lngColIndex) 
     next 
    next 
end function 

OK,一點背景知識。參數ds是在引用的ActiveX DLL中定義的OtherDLL.BaseObj類型。 ds.Data是一個變體的二維數組(一維承載數據,另一個承載列索引)ds.Columns是'ds.Data`中的列的集合

假設至少有400行數據, 25列,這個代碼大約需要15秒,我的機器上運行的類的令人難以置信的

但是如果我的變量數組複製到一個局部變量,所以:。

function Foo(ds as OtherDLL.BaseObj) 
    dim lngRowIndex as long 
    dim lngColIndex as long 
    dim v as variant 

    v = ds.Data 
    for lngRowIndex = 1 to ubound(v, 2) 
     for lngColIndex = 1 to ds.Columns.Count 
      Debug.Print v(lngRowIndex, lngColIndex) 
     next 
    next 
end function 

整個事情的過程中幾乎沒有任何顯着的時間(基本接近於0)。

爲什麼?

回答

2

很可能是ds.Data每次訪問時都會創建/複製整個數組(例如,通過從數據庫中提取數據或其他東西),並且這會花費大量時間。

通過在循環內訪問它,您就可以進行數百次這種複製操作。在第二種情況下,您只需將它複製到循環外的局部變量中,然後快速重複使用該數據數百次,而無需再次實際複製它。

這是一個常見且非常重要的優化技術:將任何不必要的工作移出循環,以便儘可能少地執行。只是在你的例子中,當你訪問數據時,並不是「顯而易見」的,它會做很多額外的工作。

+0

請注意:財產'getters'可以執行計算(甚至有副作用) – 2010-04-22 06:00:49

+0

@Jason Williams。這是我檢查的第一件事。吸氣劑不會從任何地方獲取任何東西。一切都在記憶中。這個getter有一個私有變量,基本上是一個二維數組。這就是它返回的結果。 – AngryHacker 2010-04-22 06:03:13

+0

如果getter是一個返回數組的屬性,則每次訪問該屬性時都會導致整個數組被複制。將其更改爲一個返回數組的GetData()方法,並避免此複製。 – 2010-04-22 06:22:33

相關問題