2015-03-04 11 views
8

Kilka faktów: Opracowaliśmy usługę wcf, która działa jako warstwa między klientami a bazą danych. Jest selfhosted i działa jako usługa Windows..NET Problemy z Garbagecollector. Bloki na 15-40 minut

Usługa przechowuje kilka pamięci podręcznych, z których największe zajmują około 1-2 GB pamięci. Całkowite zużycie pamięci wynosi zwykle około 5-8 gb. Połączenia są dupleksowe i używają protokołu TCP, a serializacja odbywa się za pomocą protobuf-net. Liczba naszych klientów podłączonych zwykle waha się od 1000-1500. Serwer to 8-rdzeniowy xeon nowszego modelu z 64-bitową pamięcią i nie działa niczym więcej niż usługa.

Problem: po upływie x ilości czasu, od dnia do tygodnia usługa jest bardzo powolna. Prośby, które trwają 0,5 sekundy, mogą zająć ponad minutę. Takie zachowanie trwa od 15 do 40 minut lub do momentu ponownego uruchomienia usługi.

Co zrobiliśmy: Sprawdziliśmy sieć i połączenie sieciowe z serwerem i nie ma problemu. Wykorzystanie procesora rośnie nieco w tym czasie od f.eks. 30% średnio do 40-50% średnio. Zrobiliśmy zrzut pamięci i nie ma logicznych blokad w kodzie, który blokuje użytkowników i niewiele działa. Naszym najnowszym leadem jest Garbage collector. W perfmon widzimy, że "% czasu w gc" stale przekracza 90%, (90-97%), a liczba kolekcji wzrasta. Zarówno GC0 i GC1. Podejrzewamy, że działa blokująca GC2, ale musieliśmy zrestartować usługę, ponieważ jest ona w produkcji, więc nie policzyła się podczas 5minowego okna, w którym uruchomiliśmy perfmon. Wykorzystanie pamięci wyniosło 7,6 GB. Uwaga: Połączenia są wyjątkowe, więc połączenia są dostępne, ale usługa ich nie obsługuje.

Moje pytania brzmią: Czy śmieciarz może się znaleźć w stanie, w którym działa i blokuje się nieprzerwanie przez ponad 15 minut? lub czy problem prawdopodobnie jest związany z jakimś innym problemem?

Nasza usługa uruchomiła GC w trybie stacji roboczej i latencymode: Interactive Teraz zmieniliśmy to na Server i SustainedLowLatency i mamy nadzieję, że to trochę pomoże. Czy możemy coś jeszcze zrobić, jeśli to jest zbieracz śmieci?

Edycja: duże wykorzystanie pamięci jest zgodne z projektem, dane w pamięciach podręcznych są duże i dostępnych jest dużo więcej pamięci.

+0

Zaproponuj, aby dowiedzieć się podstawową przyczyną wysokiego wykorzystania pamięci ... np. spróbuj dodać blok "używając", aby zwolnić pamięć po skończeniu używania tego obiektu. – User2012384

+0

Po prostu z ciekawości, ile wątków masz? Sprawdź w Menedżerze zadań. Przynajmniej kilka lat temu pojawił się problem, że im więcej wątków miałeś (nawet bezczynności), tym wolniej GC – xanatos

+2

"Czy odśmiecacz może uzyskać stan, w którym działa i blokuje się nieprzerwanie przez ponad 15 minut"? Absolutnie, jeśli ciągle musi zwolnić pamięć, ale nie jest w stanie, ponieważ trzymasz się jej. Jak ujął to Raymond Chen, "pamięć podręczna o złej polityce to kolejna nazwa wycieku pamięci". –

Odpowiedz

4

Nadmierne usuwanie śmieci jest często spowodowane problemami z kodem. Możesz utworzyć zbyt wiele obiektów w krótkim czasie lub alokować pamięć bez zwalniania jej.

Istnieje rzeczywiście extensive checklist available on MSDN, który powinien pomóc w zdiagnozowaniu problemu.

Bardzo duży GC2 oznacza, że ​​znajdujące się w nim obiekty przetrwały wiele wyrzucania śmieci, co oznacza, że ​​są przechowywane w pamięci przez dłuższy czas. To może być przyczyną twojego problemu. Być może istnieje mechanizm buforowania, który może korzystać z niektórych zasad strojenia/przechowywania (usuń dane, które nie są używane przez długi czas).

+0

Nasza największa pamięć podręczna jest mniej więcej zbiorem niezmiennym, dodaje dane, gdy zostaną o to poproszone i ich brakuje. Ten element ma 4 godziny ttl, jeśli nie jest on dostępny ponownie, licznik jest resetowany. Jest to bardzo proste. Typowym scenariuszem jest to, że rośnie do 1-1,5 gb na początku dnia. następnie dodaje 0,5 gb nowych danych i usuwa 0,5 gb, aw nocy jest całkowicie wyczyszczony. Jeśli jest to pamięć podręczna, która jest problemem, chciałbym móc powiedzieć gc, aby w ogóle jej nie dotykała podczas dnia i skanowała go w nocy. Czy otrzymam to zachowanie, jeśli ustawię Sustainedlowlatency, a następnie wymuszam gc.collect w nocy? –

+0

Johan: jeśli to ustawisz, GC będzie nadal przychodzić częściej niż raz dziennie. GC jest procesem ciągłym. Zwróć uwagę na sekcję uwag na temat ['GCLatencyMode'] (https://msdn.microsoft.com/en-us/library/system.runtime.gclatencymode%28v=vs.110%29.aspx): "Zbiory pełne blokowania mogą nadal występować, jeśli system znajduje się pod presją pamięci." –

+0

Jeśli chciałbym mieć dużą, trwałą pamięć podręczną w .net. W jaki sposób zrealizować to w taki sposób, aby GC nie zepsuło mojego wykonania? Chcę powiedzieć, kiedy sprawdzić? Hosting CLR z zachowaniem czy co? –

0

Mam podobną sytuację. Duża pamięć podręczna danych bazy danych w usłudze używającej protobuf z WCF do komunikacji z klientem. Pamięć podręczna nie jest przeznaczona wyłącznie dla klientów, a warstwa biznesowa używa pamięci podręcznej do wykonywania operacji. Objętość pamięci w usłudze może wynosić od 2 do 10 GB. Uwalniam segment pamięci podręcznej po 8 godzinach bezczynności. Maszyna ma 8 rdzeni wirtualnych i 32 GB pamięci. Używam .Net 4.5.1.

GC będzie zużywał 98% mocy procesora przez godzinę, gdy tylko załaduję pamięć podręczną z bazy danych. Ciekawym punktem tutaj w obu naszych przypadkach nie ma presji pamięci, co tak zawsze.

Myślę, że GC jest wykonywany niezależnie, ponieważ coś się zmieniło, gdy GC próbuje zachować dostępną pamięć dla wszystkich wątków. Ponieważ jeden wątek alokował dużą ilość pamięci podczas ładowania pamięci podręcznej, GC zaczął działać. Musiałem zrobić kilka rzeczy, aby to naprawić.

1) Usunięto Krotki z pamięci podręcznej. Używałem ich jako kluczy słownika, a ich implementacja StructuralEquality jest okropna. Porównuje on wszystkie właściwości jako obiekty, więc istnieje wiele boksów dla właściwości, które są wartościami i te będą musiały być zebrane w pewnym momencie.

2) Kiedy zastępuję Krotki używane jako klucze, nie mogłem po prostu zastąpić ich strukturami bez implementacji równań, ponieważ porównanie wartości używa odbicia i jest zbyt kosztowne, dlatego stworzyłem strukturę Rodzajową parę. Postanowiłem użyć struktur do usunięcia liczby obiektów, gdy były w tablicach.

3) Aby usunąć krotki, musiałem utworzyć własną strukturę par, która porównuje właściwości przy użyciu domyślnych równań dla typów nieruchomości. To samo, co stworzone przez PowerCollections.

Powiązane problemy