2012-05-21 8 views
8

W przypadku niektórych asynchronicznych kodów serwera tcp, czasami pojawia się błąd, który powoduje, że proces zużywa całą pamięć systemu. Patrząc na logi, przeglądarkę zdarzeń i niektóre z nich, MS docs pojawia się problem, jeśli "aplikacja wywołująca wykonuje Asynchroniczne wywołania IO do tego samego klienta wiele razy, wtedy możesz zauważyć fragmentację sterty i prywatny bajt, jeśli zdalny klient zatrzyma koniec I/O ", co skutkuje skokami zużycia pamięci i przypinaniem macierzy struct i bee System.Threading.OverlappedData.Jak zatrzymać asynchroniczny kod .cc? .NET wykorzystując całe zasoby systemu.

Proponowane przez artykuł KB rozwiązanie polega na "ustawieniu górnej granicy na ilość buforów zaległych (wysyłanie lub odbieranie) z ich asynchronicznym IO."

Jak to zrobić? Czy to odnosi się do bajtu [], który jest wysyłany do BeginRead? Czy rozwiązanie polega po prostu na owijaniu bajtu dostępu [...] za pomocą semafora?

EDYCJA: Dostęp kontrolowany semaforowo do buforów bajtowych lub po prostu posiadanie bufora bajtów o wielkości statycznej to dwa typowe rozwiązania. Obawiam się, że ten problem asynchronizujący się z klientem (może to rzeczywiście dziwne zdarzenie sieciowe) mający semafory lub pule buforów bajtowych, uniemożliwi mi wyczerpanie pamięci, ale to nie rozwiązuje problemu. Moja pula buforów prawdopodobnie zostanie pochłonięta przez problemowego klienta (ów), w efekcie blokując prawidłową funkcję legalnych klientów.

EDYCJA 2: Przyszedł na to wspaniałe answer. Zasadniczo pokazuje, jak ręcznie odpiąć obiekty. A podczas gdy asynchroniczny kod TCP pozostawia się za regułami środowiska wykonawczego sceny, możliwe jest nadpisanie tego przez jawne przypinanie każdego bufora przed użyciem, a następnie odpinanie na końcu bloku lub w końcu. Próbuję to teraz zrozumieć ...

+0

Prawdopodobny duplikat: http://stackoverflow.com/questions/236171/net-does-not-hange-reliable-asynchronouos-socket-communication – Dennis

+0

Chodzi o zawijanie wywołania BeginRead z semaforem. – mikalai

+0

Może to dobry powód, aby profilować kod ... – gsscoder

Odpowiedz

3

Jednym ze sposobów rozwiązania problemu jest wstępne przydzielenie buforów i innych struktur danych używanych w komunikacji asynchronicznej. Jeśli dokonasz wstępnej alokacji przy uruchomieniu, nie będzie fragmentacji, ponieważ pamięć będzie naturalnie znajdować się w tym samym obszarze sterty.

Polecam używanie ReceiveAsync/SendAsync API dodaje się do .NET 3.5 SP1, który pozwala buforować lub wstępnie przeznaczyć zarówno strukturę SocketAsyncEventArgs i bufor pamięci przechowywanej w SocketAsyncEventArgs.Buffer nieruchomości, w przeciwieństwie do starszych BeginXXX/EndXXX API, które pozwalają jedynie buforowanie lub wstępne przydzielanie bufora pamięci.

Korzystanie ze starego interfejsu API również wiązało się ze znacznymi kosztami procesora, ponieważ interfejs API wewnętrznie tworzył wielokrotnie nakładające się struktury we/wy systemu Windows. W nowym API odbywa się to w ramach SocketAsyncEventArgs, a więc poprzez łączenie tych obiektów koszt procesora jest wypłacany tylko raz.

Jeśli chodzi o aktualizację przypinania: przypinanie jest z jakiegoś powodu, a mianowicie, aby zapobiec przesunięciu bufora przez GC podczas defragmentacji. Odpinanie ręczne może spowodować uszkodzenie pamięci.

Powiązane problemy