2013-03-08 35 views
2

背景: 我有一個服務,其目的是爲請求者提供對象 - 它基本上從數據庫中獲取複雜數據並將其轉換一次(有點像數據視圖)以生成一個簡單的記錄。然後通過按需提供最多10萬條記錄(取決於請求的性質)來處理來自其他服務的請求。優化長壽命對象的收集

這個想法是,複雜的轉換隻需完成一次,然後通過服務進行緩存 - 比每次訪問視圖時都要讓數據庫解決問題的速度更快,而且對於我的目的而言工作得很好。 (我相信這是由一些所謂的SSOS)

數據被緩存的方式是在爲物業袋標準.NET類型對象的列表。這些對象沒有任何其他引用。 定期記錄將會改變,並且必須更新緩存,這意味着原始記錄必須被定位,丟棄並被替換。

現在在高速緩存中的記錄會一直在那裏很長一段時間,並會被標記爲第2代集合;幾乎所有的收藏品都會在Gen2階段發生,因爲這些物品已經存在了很長時間(有意)。

所以我的第二代收藏的理解是,他們是緩慢的,如果集合工作主要是在第二代則優化會更經常地做到這一點。

我希望能夠以引用完整Gen2集合的方式去除列表中的某個對象......我想也許有一種將它標記爲Gen0的方法然後在更換之前取消參考 - 但我認爲這是不可能的。

我不得不使用.NET 4中,這和應用是用作數據多達100個客戶端請求誰完整列表,或更改列表一段時間的服務。

問題:任何人都可以提出一個方式去參考長期生活的對象在GC友好的方式或者是另一種方式來解決這個問題?

+3

您目前是否有任何內存/性能問題? – ken2k 2013-03-08 12:50:33

+0

是的,它在內存使用上運行很熱。我把它降到了1GB(峯值) - 但它正在做很多處理 - 在同時查詢/序列化/向大量客戶端提供大量數據時,最高可以使用高達70%的cpu。這就是爲什麼我已經開始關注GC性能,看看我能做些什麼來獲得大量的處理能力。我知道我也有一個線程問題 - 但不認爲我可以(或者想 - 我需要讓管理層有理由移到4.5!)修復,直到我能夠移動到.net 4.5並使用異步/等待模型釋放線程。 – Jay 2013-03-08 12:54:22

+0

@Jay注意到由此引起的GC perf將限於週期性尖峯(通常相當可預測/均勻間隔)。它不會改變*集合之間的性能*。所以,如果你的應用程序已經很熱,你可能會看錯了。 – 2013-03-08 12:56:10

回答

6

對此沒有簡單的答案。如果你有很多長壽命的物品,那麼完整的收藏品真的會受到傷害,因爲我discussed here。由於圖片講述了千言萬語:

enter image description here

那些垂直尖峯其中垃圾收集發生和屠殺的響應時間。

我們減少這種影響的方式是:沒有gazillion長壽命的物體。我們所做的是將類更改爲struct s,這意味着唯一的對象是包含它們的數組。我們幸運的是,數據很簡單,並沒有涉及到string,這當然本身就是對象。我們也做了一些瘋狂的fixed-size buffer工作,以減少的事情,以前的集合,並改變了什麼是引用指數(進入陣列)。如果您必須使用string數據,也許儘量確保您不會有20,000個警報不同string instancs具有相同值 - 某種手工interner的(一個Dictionary<string,string>就足夠了),可以真正有用的存在。

注意,這種需求不會影響您的公共 API,因爲你總是可以創建一個從struct存儲舊class數據 - 不同的是,這將class只是簡單地存在,作爲一個DTO - 因此將收集便宜在下一代gen-0掃描中。

YMMV,但這對我們來說工作得不錯。

問題是:您需要是真的謹慎使用struct s;我強烈建議讓他們不變。

+0

感謝這篇偉大的文章,並給我新的想法。 – Jay 2013-03-08 14:43:06