2012-09-16 71 views
1

我有一個相當複雜的F#應用程序,我使用F#腳本使用#time指令來檢查其性能。這個想法是我在修改代碼後運行腳本以跟蹤性能並避免引入速度或內存問題。解釋F#垃圾回收報告

我得到的報告是這樣的:

Real: 00:00:02.908, CPU: 00:00:02.948, GC gen0: 237, gen1: 3, gen2: 1 

但最後一次更改後我得到這個:

Real: 00:00:03.058, CPU: 00:00:03.057, GC gen0: 262, gen1: 262, gen2: 0 

和我有一些麻煩搞清楚是怎麼回事。

更多第1代垃圾回收意味着在第0代垃圾收集中存在更多長壽命對象 - 但爲什麼突然從3跳到262?爲什麼第0代和第1代垃圾收集數量相同?如果代碼後因故改變有我本來期望像更長壽的對象:

Real: 00:00:02.908, CPU: 00:00:02.948, GC gen0: 212, gen1: 54, gen2: 1 

即是類似的垃圾收集的對象的總數,但更上一代1

或者我完全誤解了這些數字(我在文檔中找不到描述)?

UPDATE

正如我完全誤解了這個號碼的評論中指出:他們是每一代,沒有對象的數量執行垃圾回收的數量。

話雖如此,我更加困惑:似乎我的應用程序將內存置於這樣一種狀態,即每一代0垃圾收集也觸發第一代,我無法想象這種狀態會是什麼。我嘗試了各種測試程序來複制這樣的行爲,但沒有運氣。

我仍然需要按照評論和提示的答案中所建議的方法來嘗試分析器。

更新2

我嘗試了CLR探查作爲評論建議 - 做我轉換我的F#腳本到程序中,並從分析器運行它。

報告我得到的是從一個#time完全不同的 - 垃圾收集:

  • 代0:279
  • 代1:5
  • 代2:2。

Mistery - 使用FSI.exe與獨立程序相比的副作用?錯誤在#time

+2

數字實際上是那一代的集合數 - 打印功能在https://github.com/fsharp/fsharp/blob/master/src/fsharp/fsi/fsi.fs-第124行 –

+1

另外,如果你真的擔心內存使用情況,CLR profiler http://www.microsoft.com/en-us/download/details.aspx?id=16273提供了比你得到的更詳細的信息從'#時間' –

+0

我想說,GC運行數量的差異將是獨立與解釋器 - FSI中的GC計數包括與編譯/優化不是獨立版本的代碼有關的GC的GC。我建議查看GC計數並不是一個好的性能指標 - 實際運行時間要好得多。 –

回答

2

.NET GC是一個三代GC。正如約翰帕爾默指出的那樣,最後三個數字是the number of collections run這幾代人。gen1gen2中的較大數字通常表示性能不佳,因爲GC必須在每個垃圾收集過程中一次又一次標記這些未使用的對象。要深入介紹.NET GC,請看this nice article

這裏有幾個建議:

  1. 確保「復位會話」兩次測量之間,使得第一屆會議未使用的對象不會對第二個產生影響。
  2. 找到三個更大的輸入來衡量。儘管這兩個報告中的執行時間相似,但我希望第一種方法更具可擴展性。如果您有幾個輸入大小來測試可伸縮性,那就太好了。
  3. 測量幾次以記錄模式,因爲您可能只會觀察到異常會話。
  4. 如果有疑問,請在Visual Studio中執行full-range profiling。他們的報告對於性能預測更加全面和可靠。
+0

我相信它是運行的集合數 - 而不是收集的對象數 - 請參閱http://msdn.microsoft .com/en-us/library/system.gc.collectioncount.aspx –

+0

@JohnPalmer:謝謝,我修正了這個問題。 – pad