6

我有一個Sitecore應用程序,我需要在另一個系統的循環中創建大量的Sitecore項目。以下是我的測試目的循環;創建大量的Sitecore項目導致內存泄漏

using (new Sitecore.SecurityModel.SecurityDisabler()) 
{ 
    for (int i = 0; i < 20000; i++) 
    { 
     Item newItem = MyTemplateItem.CreateItemFrom(DateTime.Now.Ticks.ToString(), myParentItem); 

     newItem.Editing.BeginEdit(); 
     newItem.Fields["Title"].Value = Guid.NewGuid().ToString(); 
     newItem.Editing.EndEdit(); 
    } 
} 

當這個循環運行期間,在看任務管理器,在進程的內存使用量越來越隨時間增加。

Sitecore Item類尚未實現IDisposable接口,所以我無法調用創建項目的終結器。

我該如何避免這種內存泄漏?

PS:我正在使用Windows應用程序執行此操作以繞過IIS進程內存泄漏,其中Sitecore執行其緩存更新和索引構建,這應在此過程結束時完成。

+0

你確定它確實是一個泄漏?你正在執行一個函數,它必須分配內存並在循環中這樣做。僅僅因爲進程內存增加並不意味着它是泄漏。記憶永遠不會下降嗎? – ddysart

+0

我認爲我的術語是正確的,內存在不斷增長,如果RAM已滿,PC將重新啓動。它是一個內存泄漏。我已經監控了大約一個小時的循環。 –

回答

3

您可將商品創建過程中暫時禁用數據庫高速緩存:

Sitecore.Configuration.Settings.Indexing.Enabled = false; 

嘗試添加這兩個東西,看看是否有幫助:

using (new Sitecore.Data.DatabaseCacheDisabler()) 

您可以使用在創建過程中禁用索引。

更新: 也許這會工作。 EndEdit中()後,你的循環裏面 補充一點:

newItem = null; 

if (i % 100 == 0) 
{ 
    GC.Collect(); 
    GC.WaitForPendingFinalizers(); 
} 

這將迫使垃圾收集想盡已添加100個項目的時間收回未使用的內存。

如果這樣做有效,那麼你不必真的自己調用GC,它會在某個時刻自動發生,你只是不知道什麼時候發生。

+0

感謝您的回覆。我嘗試了你的建議,但是我對內存的增長沒有任何改變。 –

+0

對我的回答增加了另一個建議 –

+0

一般來說,你應該避免調用GC.Collect,因爲它是一個非常耗費CPU資源的進程,它會阻止整個AppPool。 – ddysart

0

Ruud的答案似乎比它更好。由於建立了數據庫緩存,內存的增長很快。通過禁用顯着減緩內存增長,但增長速度仍然非常緩慢。

我已經使用以下語句來實現它;

using (new Sitecore.Data.DatabaseCacheDisabler()) 

newItem = null; // did not worked 

// replaced above line with the below 
Marshal.Release(Marshal.GetIUnknownForObject(newItem)); 

if (i % 100 == 0) 
{ 
    GC.Collect(); 
    GC.WaitForPendingFinalizers(); 
} 

感謝所有的支持者!

0

如果您將緩存限制設置爲較高值(即太高)並執行您正在做的操作,那麼獲取您要報告的症狀似乎是合理的。腳本運行時查看頁面/sitecore/admin/cache.aspx將顯示是否屬於這種情況。我倒是圖像條目master[items]master[data]將繼續攀登......

如果的情況下,簡單地設置一個較低的緩存限制將意味着緩存需要被清空,這似乎是一個更健康的方式來保持事情在控制之中。

另外,如果你想大大加快編程項目的創建,也許嘗試使用

using (new BulkUpdateContext()) { code.. }

這有可能是BulkUpdateContext()也跳過添加項目到緩存 - 我沒有,如果這個檢查是這樣的,但如果是這樣的話,它也可能會「解決」你所擁有的內存問題。

(也參見this SO answer)。請注意,它會禁用多個管道。