2012-03-28 19 views
5

Aktualnie programuję aplikację kliencką i zastanawiam się, czy powinienem użyć klasy Socket "ReceiveAsync lub BeginReceive. Do tej pory używałem tego ostatniego, jednak zauważyłem, że wydaje się mocno obciążać procesor. Oto co mój otrzymać pętlę zasadniczo wygląda następująco:Wydajność metody ReceiveAsync vs. BeginReceive

private void socket_ReceiveCallback(IAsyncResult result_) 
{ 
    // does nothing else at the moment 
    socket.EndReceive(result_); 
    byte[] buffer = (byte[])result_.AsyncState; 

    // receive new packet 
    byte[] newBuffer = new byte[1024]; 
    socket.BeginReceive(newBuffer, 0, newBuffer.Length, SocketFlags.None, 
         socket_ReceiveFallback, newBuffer); 
} 

Teraz Zastanawiałem się, czy robię coś źle tutaj, ponieważ inne aplikacje, które komunikują się z trudem stres procesora w ogóle. Zastanawiam się też, czy lepiej byłoby używać SocketAsyncEventArgs i ReceiveAsync.

Więc oto moje pytania:

Dlaczego moja pętla podkreślając CPU tak dużo? Czy powinienem używać SocketAsyncEventArgs i ReceiveAsync zamiast BeginReceive?

+0

założę to becuase dzwonisz swoją meto d w pętli, w której nie ma blokowania, więc maksymalizujesz jeden z rdzeni - użyj klasy ManualResetEvent, aby w razie potrzeby wykonać blokowanie ręczne. – markmnl

+0

Czy "socket_ReceiveFallback" jest rzeczywiście inną metodą w twoim wdrożeniu? – markmnl

Odpowiedz

5

Przeprowadzałem analizę porównawczą synchronicznego względem asynchronicznego gniazda na połączeniu pętli localhost. Moje wyniki były takie, że asynchroniczna wersja była o około 30% wolniejsza. Było to dla mnie zaskakujące, biorąc pod uwagę, że asynchroniczne IO jest teraz wszystkim wściekłością. Nie miało znaczenia, ile wątków użyłem. Mógłbym używać 128 wątków i nadal synchroniczne IO było szybsze.

Powodem tego jest, moim zdaniem, że asynchroniczne IO wymaga więcej alokacji i więcej przejść w trybie jądra.

Możesz więc przełączyć się na synchroniczne IO, jeśli nie spodziewasz się setek równoczesnych połączeń.

+0

Łączę się tylko z jednym serwerem. Mogę więc po prostu użyć zwykłych metod odbierania i wysyłania? Jeśli chcę, aby był asynchroniczny, mógłbym stworzyć całą klasę w innym wątku, który prawdopodobnie nie byłby tak powolny. – haiyyu

+1

Zdecydowanie testowałem tę opcję. Domyślam się, że synchroniczna wersja będzie szybsza. I więcej do utrzymania! – usr

+0

Zrobię to i opublikuję wyniki później. Miałem również na myśli "Mogłem stworzyć cały obiekt (nie klasę) w innym wątku". – haiyyu

1

Odpowiedz na to pytanie, musisz profilować swoją aplikację. Co Zastanawiam jest

  • dlaczego nie widzę EndReceive
  • dlaczego nie używasz odebranego bufora w ogóle i
  • dlaczego można przydzielić nowy raz po raz bufory - to tylko opperation tutaj, że należy podejmować żadnych zasobów (CPU/pamięci)

Wystarczy popatrzeć na to: http://msdn.microsoft.com/de-de/library/dxkwh6zw.aspx

+0

1) Przepraszamy, zapomniałem dodać do kodu. Jest tam w programie. Zmieniłem mój post. 2) Planuję go użyć. Jednak nawet bez jego użycia serwer bardzo mocno obciąża procesor. 3) Czy byłoby lepiej stworzyć pulę buforów? Zrobię to i sprawdzę, czy coś zmieni! Dzięki za pomoc. – haiyyu

+0

Moim zdaniem w tym momencie domyślam się, że ponieważ przenosisz tylko małe bloki (1kB) i robisz to bez opóźnienia - nie ma zbyt wiele czekania, aż sprzęt to zrobi (nawet bardziej prawdziwe, jeśli robisz to na tym samym komputerze) , więc system jest zajęty tworzeniem połączeń asynchronicznych. Ale naprawdę polecam znalezienie dobrego profilera (większość ma testy) lub nawet używając wbudowanego (myślę, że VS prof lub większy), aby znaleźć słaby punkt – Carsten

Powiązane problemy