2010-03-25 6 views
10

Wszystko, co czytałem o gniazdach w .NET, mówi, że asynchroniczny wzorzec zapewnia lepszą wydajność (szczególnie w przypadku nowej SocketAsyncEventArgs, która zapisuje przydział).Synchronizuj vs. Async Sockets Performance w .NET

Myślę, że ma to sens, jeśli mówimy o serwerze z wieloma połączeniami klientów, gdzie nie można przydzielić jednego wątku dla jednego połączenia. Wtedy widzę zaletę używania wątków ThreadPool i otrzymywania asynchronicznych wywołań zwrotnych na nich.

Ale w mojej aplikacji jestem klientem i muszę tylko wysłuchać jednego serwera wysyłającego dane rynkowe za pośrednictwem jednego połączenia tcp. W tej chwili tworzę pojedynczy wątek, nadaję najwyższy priorytet i wywołuję z nim Socket.Receive(). Moja nić blokuje to połączenie i budzi się, gdy nadejdą nowe dane.

Gdybym przełączyć to na wzór asynchroniczny, tak aby uzyskać wywołania zwrotnego, gdy pojawia się nowe dane, widzę dwie kwestie

  1. wątków puli wątków będzie mieć domyślny priorytet więc wydaje się będą ściśle gorszy niż mój własny wątek, który ma najwyższy priorytet.

  2. Nadal będę musiał wysłać wszystko przez jeden wątek w pewnym momencie. Załóżmy, że otrzymuję N callbacków prawie w tym samym czasie na N różnych wątkach wątku, powiadamiając mnie, że są nowe dane. Nioskowane przez nią tablice N nie mogą być przetwarzane w wątkach wątków, ponieważ nie ma gwarancji, że reprezentują N unikatowych komunikatów danych rynkowych, ponieważ TCP jest oparty na strumieniu. Będę musiał zablokować i umieścić bajty w tablicy i sygnalizować inny wątek, który może przetworzyć to, co jest w tablicy. Nie jestem więc pewien, co mnie kupiło N wątków z wątków.

Czy myślę o tym źle? Czy jest jakiś powód używania Async w moim konkretnym przypadku jednego klienta podłączonego do jednego serwera?

UPDATE:

Więc myślę, że było błędnie rozumiejąc wzór asynchronicznej w (2) powyżej. Otrzymałbym wywołanie zwrotne w jednym wątku roboczym, gdy były dostępne dane. Wtedy zacznę inny async odbierać i uzyskać inny oddzwanianie, itp. Nie dostanę N zwrotów w tym samym czasie.

Pytanie pozostaje jednak takie samo. Czy jest jakiś powód, że callbacks byłyby lepsze w mojej konkretnej sytuacji, w której jestem klientem i tylko podłączony do jednego serwera.

Odpowiedz

5

Najwolniejszą częścią aplikacji będzie komunikacja sieciowa. Jest bardzo prawdopodobne, że prawie nie zmienisz wydajności jednego wątku, jednego klienta połączenia, ulepszając takie rzeczy. Sama komunikacja sieciowa skłoni wszystkie inne wkłady do przetwarzania lub czasu przełączania kontekstu.

Załóżmy, że mam N zwrotnych w prawie tym samym czasie na n różnych puli wątków wątków powiadamiania mnie, że tam nowe dane.

Dlaczego tak się stanie? Jeśli masz jedno gniazdo, musisz wykonać operację, aby odebrać dane, a po zakończeniu otrzymasz dokładnie jedno wywołanie zwrotne. Następnie decydujesz, czy wykonać kolejną operację. Wygląda na to, że nadmiernie komplikujesz to, choć może upraszczam to w odniesieniu do tego, co próbujesz zrobić.

Podsumowując, powiedziałbym: wybierz najprostszy model programowania, który zapewni Ci to, czego chcesz; biorąc pod uwagę wybory dostępne w twoim scenariuszu, prawdopodobnie nie będą miały zauważalnej różnicy w działaniu, w zależności od tego, z którym idziesz. W przypadku modelu blokującego "marnujesz" wątek, który może wykonać jakąś prawdziwą pracę, ale hej ... może nie masz za to żadnej prawdziwej pracy.

+0

Dzięki za odpowiedź. Masz rację, patrzyłem na ten przykład źle. Dlatego zaczynam i odbieram wywołanie zwrotne w wątku threadpool, gdy są dane. Przetwarzam go i mogę zdecydować, że chcę dalej słuchać więcej i uzyskać kolejne wywołanie zwrotne. Ale nawet jeśli tak jest, nie widzę, jak to może być szybsze niż posiadanie jednego wątku o wysokim priorytecie poświęconego wykonywaniu funkcji Receive(). –

+0

Po pierwsze, powinienem unikać ustawiania priorytetu wątków. Jestem prawie pewien, że generalnie nie jest to zalecane. Lepiej pozwolić wszystkim wątkom, które mają pracę do wykonania, uzyskać równy dostęp do procesora. Po drugie, moim celem jest to, że * nie * będzie szybsze. Wartość asynchronicznych API polega na tym, że pozwalają uniknąć wiązania wątku (kosztowny zasób ze względu na rozmiar stosu wywołań) w czystym czekaniu, a jeśli masz tylko jedno połączenie i jeden wątek i nic nie możesz zrobić, dopóki odzyskać dane, wtedy naprawdę nie ma wielkich kosztów związanych z zawiązaniem jednego wątku. Wyjątkiem jest użycie Silverlight, ponieważ ma tylko asynchroniczne. –

+0

"Faster" jest prawie całkowicie dyskusyjny w tym scenariuszu, ponieważ tego rodzaju wybory zostaną utracone w hałasie w porównaniu do kosztu samej komunikacji sieciowej.Dosłownie nic nie zyskuje na wydajności, przełączając się między tymi technikami. –

3

Zasada numer jeden pod względem wydajności polega jedynie na poprawieniu go, gdy jest to konieczne.

Widzę, że wymieniasz standardy, ale nigdy nie wspominasz o problemach, jeśli ich nie masz, nie musisz się martwić, co mówią standardy.

+0

To prawda, teraz nie ma problemu. Ale trudno to zmierzyć. Mógłbym skonfigurować dwie wersje aplikacji, jedną z wzorcem asynchronicznym i jedną z wzorcem synchronizacji i zmierzyć. Ale byłoby miło wiedzieć, czy ktoś już to zrobił i może mi powiedzieć, że asynchronizacja będzie szybsza i dlaczego. –

2

"This class was specifically designed for network server applications that require high performance. "

Jak rozumiem, jesteś klient tutaj, mając tylko pojedynczy połączenia.
Dane na ten związek przybywa w porządku, spożywane przez jednego wątku.

Prawdopodobnie utracisz wydajność, jeśli zamiast tego odbierze niewielkie ilości na osobnych wątkach, tak abyś mógł je złożyć później w postaci zserializowanej - a więc tak jak w przypadku pojedynczego gwintowania -. Wiele hałasu o nic.


Nie musisz tego przyspieszać, prawdopodobnie nie możesz tego zrobić.

Co może zrobić, jednak jest wysłanie jednostek pracy do innych wątków po po ich otrzymaniu. Nie potrzebujesz do tego SocketAsyncEventArgs. To może przyspieszyć rzeczy.

Jak zawsze zmierzyć miarę &.
Ponadto, tylko dlatego, że możesz, nie oznacza to, że powinieneś.
Jeśli wydajność jest wystarczająca w najbliższej przyszłości, dlaczego komplikuje sprawę?

+0

Zgadzam się. Takie też było moje myślenie. Jeśli mogę uzyskać wiele wywołań zwrotnych w wielu wątkach ThreadPool, wydaje się to złym pomysłem. Ale byłem sceptyczny, ponieważ każdy artykuł na temat gniazda, który czytałem dla gniazd .NET mówi, jak świetne są gniazda asynchroniczne (i jestem pewien, że są one dużo lepsze dla wielu aplikacji). Chciałem tylko upewnić się, że nie pominąłem czegoś dla mojej konkretnej sprawy. –