6

Mam aplikację Sitecore, w której potrzebuję utworzyć dużą liczbę elementów Sitecore w pętli z innego systemu. Poniżej znajduje się moja pętla celu testowania;Tworzenie dużej ilości elementów Sitecore powoduje wyciek pamięci

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(); 
    } 
} 

Gdy ta pętla jest uruchomiona i podczas przeglądania w menedżerze zadań, zużycie pamięci procesowej wzrasta wraz z upływem czasu.

Sitecore Item klasa nie zaimplementowała interfejsu IDisposable, więc nie mogę wywołać Finalizatora utworzonego elementu.

Jak mogę uniknąć wycieku pamięci?

PS: Używam aplikacji Windows do wykonania tej operacji w celu obejścia przecieku pamięci procesu IIS, gdzie Sitecore wykonuje aktualizację pamięci podręcznej i tworzenie indeksu, co powinno zostać wykonane na końcu tego procesu.

+0

Czy jesteś pewien, że to naprawdę wyciek? Wykonujesz funkcję, która musi alokować pamięć i robić to w pętli. To, że pamięć procesowa idzie w górę, nie oznacza, że ​​jest to przeciek. Czy pamięć nigdy nie zanika? – ddysart

+0

Myślę, że moja terminologia jest poprawna, pamięć ciągle rośnie i jeśli pamięć RAM jest pełna, komputer zostanie ponownie uruchomiony. To przeciek pamięci. Monitorowałem pętlę przez około godzinę. –

Odpowiedz

3

można czasowo wyłączyć pamięć podręczną bazy danych podczas tworzenia elementu:

using (new Sitecore.Data.DatabaseCacheDisabler()) 

Można wyłączyć indeksowanie podczas tworzenia przy użyciu:

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

spróbuj dodać te dwie rzeczy i zobaczyć, czy to pomaga .

AKTUALIZACJA: Może to zadziała. Dodaj to wewnątrz pętli po EndEdit():

newItem = null; 

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

To zmusi śmieciarza, aby spróbować odzyskać nieużywaną pamięć za każdym razem 100 sztuk zostały dodane.

Jeśli to zadziała, to nie musisz sam dzwonić do GC, stanie się to automatycznie w pewnym momencie, po prostu nie wiesz kiedy.

+0

Dzięki za odpowiedź. Próbowałem twoich sugestii, ale nie mam zmian w rozwoju pamięci. –

+0

Dodałem kolejną sugestię do mojej odpowiedzi –

+0

Ogólnie należy unikać wywoływania GC.Collect, ponieważ jest to proces bardzo obciążający procesor, który blokuje cały AppPool, podczas gdy robi to. – ddysart

0

Odpowiedź Ruuda wydaje się działać lepiej niż była. Wzrost pamięci był szybki z powodu budowania pamięci podręcznej bazy danych. Przez wyłączenie drastycznie spowalnia się wzrost pamięci, ale mimo to wzrost następuje bardzo powoli.

Użyłem następujących oświadczeń, aby to osiągnąć;

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(); 
} 

Dzięki za wszystkich kibiców!

0

Jeśli ustawisz limity pamięci podręcznej na wysokie wartości (tj. Zbyt wysokie) i zrobisz to, co robisz, rozsądne wydaje się zgłaszanie zgłaszanych przez Ciebie symptomów. Patrząc na stronę /sitecore/admin/cache.aspx podczas działania skryptu, pokaże się, czy tak jest. Ja bym obraz wpisy master[items] i master[data] będzie kontynuować wspinaczki ...

Jeśli jest przypadek, po prostu ustawiając dolną granicę cache będzie oznaczać bufory są opróżniane w miarę potrzeb, co wydaje się zdrowszy sposób, aby zachować rzeczy pod kontrolą.

Ponadto, jeśli chcesz, aby znacznie przyspieszyć programowego tworzenia elementu, może spróbować użyć

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

Jest możliwe, że BulkUpdateContext() pomija także dodawanie elementów do pamięci podręcznej - Nie sprawdzałem, czy to tak jest, ale jeśli tak, to prawdopodobnie "naprawi" problem z pamięcią.

(patrz także this SO answer). Zauważ, że blokuje kilka potoków.