Mam komponent serwera, który działa na Zeroc-ICE. Kiedy chciałem załadować test, pomyślałem, że skorzystanie z biblioteki równoległej do utworzenia wielu żądań to wystarczy. Ale tak się nie kończy. Korzystanie z biblioteki Parallel (Parallel.For) z C # najwyraźniej było łatwiejsze, ale nie wydaje się, aby dokładnie generowało wszystko równolegle w tym samym momencie. Nie może to być definicja tworzenia N żądań na sekundę. Jak mam to zrobić? Myślę, że każdy, kto chce najpierw przeprowadzić test obciążenia, naprawdę by o tym pomyślał.
Jaki jest efektywny sposób tworzenia N żądań w ciągu sekundy?
Kolejny mit dotyczy programowania równoległego. Proszę nas oświecić, jeśli użyliście wzorców programowania równoległego w C # lub .Net w ogóle. Wyobraź sobie, że mam 5 procesów. Jak rozpocznie się wszystkie pięć procesów jednocześnie. Co to znaczy dla mojego zużycia zasobów? Próbowałem zapoznać się z wieloma materiałami dostępnymi w sieci, ale otrzymuję coraz więcej pytań niż odpowiedzi na moje pytania.
Użyłem Parallel.For i stworzyłem N wątków i zmierzyłem czas. Następnie spróbowałem tego samego za pomocą Task.Factory.start do wyliczenia zadań. Zmierzony czas był inny. Więc czym dokładnie różni się używanie ich? Kiedy powinienem używać odpowiednich klas i do jakich celów? często mamy wiele bogactw, ale po prostu nie wiemy, jak odróżnić jedno od drugiego. To dla mnie jeden taki przypadek, ponieważ nie mogę znaleźć powodu, dla którego nie powinienem używać jednego od drugiego.
Użyłem klasy stopera, aby zmierzyć te czasy, które uważają za najlepsze. W scenariuszu obciążenia testuję komponent, jaki byłby sposób pomiaru czasu odpowiedzi. Stoper wydaje mi się najlepszym rozwiązaniem dla mnie. Wszelkie opinie są mile widziane.
ps: Istnieje wiele narzędzi do testowania obciążenia dla aplikacji internetowych. Mój jest niestandardowym przypadkiem komponentów serwera. Moje pytanie dotyczy bardziej tworzenia N wątków na sekundę.
Wszystkie opinie są mile widziane. Tylko nie myśl, że to nie tyle pytanie programistyczne. Oczywiście jest. Powinien zadzwonić do każdego programisty, który chce samodzielnie sprawdzić jakość swojego produktu, aby samemu poznać wydajność swojego produktu. Próbowałem wielu opcji, a potem musiałem się zastanowić, jak powinienem to zrobić?
źródło
Odpowiedzi:
Nie mam wszystkich odpowiedzi. Mam nadzieję, że mogę rzucić na to trochę światła.
Aby uprościć moje poprzednie stwierdzenia dotyczące modeli wątków .NET, wystarczy wiedzieć, że Parallel Library używa Tasks, a domyślny TaskScheduler dla Tasks używa ThreadPool. Im wyżej w hierarchii (ThreadPool znajduje się na dole), tym więcej narzutów masz przy tworzeniu elementów. To dodatkowe obciążenie z pewnością nie oznacza, że jest wolniejsze, ale dobrze wiedzieć, że tam jest. Ostatecznie wydajność twojego algorytmu w środowisku wielowątkowym sprowadza się do jego konstrukcji. To, co działa dobrze sekwencyjnie, może nie działać równie dobrze równolegle. Jest zbyt wiele czynników, aby dać ci twarde i szybkie reguły, zmieniają się w zależności od tego, co próbujesz zrobić. Ponieważ zajmujesz się żądaniami sieci, postaram się podać mały przykład.
Pozwól mi powiedzieć, że nie jestem ekspertem od gniazd i nie wiem prawie nic o Zeroc-Ice. Wiem trochę o operacjach asynchronicznych i właśnie tam naprawdę ci to pomoże. Jeśli wyślesz żądanie synchroniczne przez gniazdo, podczas połączenia
Socket.Receive()
Twój wątek zostanie zablokowany do momentu otrzymania żądania. To nie jest dobre. Wątek nie może wysyłać więcej żądań, ponieważ jest zablokowany. Za pomocą Socket.Beginxxxxxx () żądanie I / O zostanie wykonane i umieszczone w kolejce IRP dla gniazda, a Twój wątek będzie kontynuowany. Oznacza to, że Twój wątek może faktycznie wysyłać tysiące żądań w pętli bez żadnego blokowania!Jeśli dobrze cię rozumiem, używasz wywołań za pomocą Zeroc-Ice w kodzie testowym, a nie próbujesz dotrzeć do punktu końcowego http. W takim przypadku mogę przyznać, że nie wiem, jak działa Zeroc-Ice. Chciałbym jednak zasugerować po poradę wymienionych tutaj , zwłaszcza część:
Consider Asynchronous Method Invocation (AMI)
. Strona pokazuje to:Co wydaje się być odpowiednikiem tego, co opisałem powyżej przy użyciu gniazd .NET. Mogą istnieć inne sposoby poprawy wydajności, gdy próbuję wykonać wiele wysyłek, ale zacznę tutaj lub z dowolnymi innymi sugestiami wymienionymi na tej stronie. Byłeś bardzo niejasny co do projektu swojej aplikacji, więc mogę być bardziej szczegółowy niż wcześniej. Pamiętaj tylko, że nie używaj więcej wątków, niż jest to absolutnie konieczne, aby uzyskać to, czego potrzebujesz, w przeciwnym razie aplikacja będzie działać wolniej niż chcesz.
Kilka przykładów w pseudokodzie (próbowałem zbliżyć się do lodu, jak to możliwe, ale ja nie musiałem się go uczyć):
Lepszy sposób:
Pamiętaj, że więcej wątków! = Lepsza wydajność podczas próby wysłania gniazd (lub naprawdę robiąc cokolwiek). Wątki nie są magiczne, ponieważ automatycznie rozwiążą każdy problem, nad którym pracujesz. Idealnie, chcesz 1 wątek na rdzeń, chyba że wątek spędza dużo czasu na oczekiwaniu, możesz uzasadnić, że masz więcej. Uruchamianie każdego żądania w jego własnym wątku jest złym pomysłem, ponieważ nastąpi zmiana kontekstu i marnowanie zasobów. (Jeśli chcesz zobaczyć wszystko, co o tym napisałem, kliknij edytuj i spójrz na poprzednie wersje tego postu. Usunąłem go, ponieważ wydawało się, że tylko zasłania główny problem.)
Zdecydowanie możesz je wysłać w wątkach, jeśli chcesz wysyłać dużą liczbę żądań na sekundę. Jednak nie przesadzaj z tworzeniem wątków. Znajdź równowagę i trzymaj się jej. Osiągniesz lepszą wydajność, jeśli użyjesz modelu asynchronicznego w porównaniu z modelem synchronicznym.
Mam nadzieję że to pomogło.
źródło
Pominę pytanie 1) i przejdę do punktu 2, ponieważ jest to ogólnie akceptowalny sposób na osiągnięcie tego, czego szukasz. W przeszłości, aby osiągnąć n wiadomości na sekundę, możesz utworzyć pojedynczy proces, który następnie uruchomi p AppDomains. Każda AppDomain po prostu zaczyna uruchamiać pętlę żądań po osiągnięciu określonego punktu w czasie (za pomocą Timera). Ten czas powinien być taki sam dla każdej AppDomain, aby zapewnić, że zaczną uderzać o serwer w tym samym momencie.
Coś takiego powinno działać przy wysyłaniu twoich wniosków:
Prawdopodobnie zmniejszy to wydajność na dowolnym komputerze, na którym go uruchomisz, więc zawsze możesz zaimplementować podobny typ pętli z kilku różnych komputerów, jeśli masz zasoby (używając procesów zamiast domen aplikacji).
W przypadku trzeciego pytania proszę przeczytać ten link na stronie http://www.albahari.com/threading/
Wreszcie, stoper powinien być sparowany z licznikiem trafień, aby śledzić zarówno czas trwania, jak i niepowtarzalne trafienia na serwerze. To powinno pozwolić ci przeprowadzić analizę po fakcie.
źródło
Nie przejmuj się wątkami, jeśli N jest stosunkowo mały. Aby wygenerować N żądań na sekundę, użyj zegara ściennego (
DateTime.Now
). Poświęć trochę czasu przed i po żądaniu, a następnie dodaj znak,Sleep
aby opóźnić następne żądanie.Na przykład przy N = 5 (200 ms):
To nie jest idealne; może się okazać, że
Sleep
to nie jest dokładne. Możesz zachować bieżącą liczbę odchyleń (przed X żądaniami czas powinien wynosić X-1 / N później) i odpowiednio dostosować okres uśpienia.Gdy N stanie się zbyt duży, wystarczy utworzyć M wątków i pozwolić, aby każdy wątek wygenerował N / M żądań w ten sam sposób.
źródło
Najłatwiejszym sposobem przeprowadzenia testu obciążenia dla dowolnego projektu .NET jest zakup wersji Ultimate programu Visual Studio. Jest wyposażony w zintegrowane narzędzia testowe, które pomagają w przeprowadzaniu wszelkiego rodzaju testów, w tym testów obciążenia. Testy obciążenia można wykonać, tworząc użytkowników wirtualnych na jednym komputerze lub rozdzielonych między kilku użytkowników dla większej liczby użytkowników. Istnieje również mały program, który można zainstalować na serwerach docelowych w celu zwrócenia dodatkowych danych na czas trwania testu.
Jest to jednak drogie, ale wersja ostateczna ma wiele funkcji, więc gdyby wszystkie były wykorzystane, byłaby to bardziej rozsądna cena.
źródło
Jeśli chcesz, aby wszystkie wątki X trafiły do twojego zasobu dokładnie w tym samym czasie, możesz umieścić każdy wątek za zatrzaskiem odliczania i określić krótki okres oczekiwania między sprawdzeniami semaforów.
C # ma implementację (http://msdn.microsoft.com/en-us/library/system.threading.countdownevent(VS.100).aspx).
Jednocześnie, jeśli testujesz system w warunkach skrajnych, możesz również sprawdzić warunki wyścigu, w którym to przypadku chcesz ustawić okresy uśpienia wątku dla każdego wątku, które oscylują w czasie z losową częstotliwością i szczytami / przerwami.
Podobnie możesz nie chcieć po prostu szybko wysyłać wielu żądań, możesz mieć większy sukces w wprowadzaniu serwera w zły stan / testowaniu jego wydajności w świecie rzeczywistym, konfigurując mniejszą liczbę wątków, które spędzają więcej czasu na konsumowaniu i wysyłaniu wiadomości z powrotem i dalej nad gniazdem, ponieważ Twój serwer prawdopodobnie będzie musiał rozwinąć własne wątki, aby obsłużyć wolno trwające wiadomości.
źródło