Udostępnij za pośrednictwem


Typowe nieprawidłowo działające wzorce dla aplikacji wielowątkowych

Wizualizator współbieżności ułatwia deweloperom wizualizowanie zachowania aplikacji wielowątku. To narzędzie zawiera galerię typowych wzorców dla aplikacji wielowątków, które zachowują się źle. Galeria zawiera typowe i rozpoznawalne wzorce wizualne, które są uwidocznione za pomocą narzędzia, wraz z wyjaśnieniem zachowania reprezentowanego przez każdy wzorzec, prawdopodobnym wynikiem tego zachowania i najczęstszym podejściem do jego rozwiązania.

Blokowanie rywalizacji i serializacji wykonywania

Lock contention resulting in serialized execution

Czasami równoległa aplikacja uparcie kontynuuje wykonywanie szeregowo, mimo że ma kilka wątków, a komputer ma wystarczającą liczbę rdzeni logicznych. Pierwszy objaw jest słabszą wydajnością wielowątkową, być może nawet nieco wolniejszą niż implementacja szeregowa. W widoku wątków nie widać wielu wątków uruchomionych równolegle; Zamiast tego widać, że tylko jeden wątek jest wykonywany w dowolnym momencie. W tym momencie, jeśli klikniesz segment synchronizacji w wątku, zobaczysz stos wywołań dla zablokowanego wątku (blokujący stos wywołań) i wątek, który usunął warunek blokowania (odblokowywanie stosu wywołań). Ponadto, jeśli odblokowanie stosu wywołań występuje w procesie, który analizujesz, zostanie wyświetlony łącznik Gotowy do wątku. Od tego momentu możesz przejść do kodu z blokujących i odblokowywania stosów wywołań, aby zbadać przyczynę serializacji jeszcze bardziej.

Jak pokazano na poniższej ilustracji, wizualizator współbieżności może również uwidocznić ten objaw w widoku wykorzystania procesora CPU, gdzie pomimo obecności wielu wątków aplikacja zużywa tylko jeden rdzeń logiczny.

Aby uzyskać więcej informacji, zobacz sekcję "Rozpocznij od problemu" w artykule Thread Performance - Resource Contention Concurrency Profilowanie w programie Visual Studio.

Lock Contention

Nierównomierna dystrybucja obciążeń

Screenshot of a workload graph for parallel threads in the Concurrency Visualizer. The threads end at different times showing a stair-step pattern.

Gdy nieregularny rozkład pracy występuje w kilku równoległych wątkach w aplikacji, typowy wzorzec schodów pojawia się, gdy każdy wątek kończy swoją pracę, jak pokazano na poprzedniej ilustracji. Wizualizator współbieżności najczęściej pokazuje bardzo bliskie godziny rozpoczęcia dla każdego współbieżnego wątku. Jednak te wątki zwykle kończą się nieregularnie zamiast kończyć się jednocześnie. Ten wzorzec wskazuje nieregularny rozkład pracy między grupą wątków równoległych, co może prowadzić do zmniejszenia wydajności. Najlepszym podejściem do takiego problemu jest ponowne obliczanie algorytmu, za pomocą którego praca została podzielona między wątki równoległe.

Jak pokazano na poniższej ilustracji, wizualizator współbieżności może również uwidocznić ten objaw w widoku wykorzystania procesora CPU jako stopniowy krok w zakresie wykorzystania procesora CPU.

Screenshot of the CPU Utilization View in the Concurrency Visualizer showing a stair-step pattern at the end of the CPU Utilization graph.

Nadsubskrypcji

Screenshot of a workload graph for all active threads in the Concurrency Visualizer. A legend shows the amount of time spent in Execution and Preemption.

W przypadku przesubskrypcji liczba aktywnych wątków w procesie jest większa niż liczba dostępnych rdzeni logicznych w systemie. Na poprzedniej ilustracji przedstawiono wyniki przesubskrypcji ze znaczącym podziałem na przedziały we wszystkich aktywnych wątkach. Ponadto legenda pokazuje duży procent czasu poświęcanego na wywłaszczanie (84 procent w tym przykładzie). Może to wskazywać, że proces prosi system o wykonanie większej liczby współbieżnych wątków niż liczba rdzeni logicznych. Jednak może to również wskazywać, że inne procesy w systemie korzystają z zasobów, które zostały przyjęte jako dostępne dla tego procesu.

Podczas oceny tego problemu należy wziąć pod uwagę następujące kwestie:

  • Ogólny system może być nadmiernie zastępowany. Należy wziąć pod uwagę, że inne procesy w systemie mogą wywłaszczać wątki. Po wstrzymaniu segmentu wywłaszczania w widoku wątków etykietka narzędzia zidentyfikuje wątek i proces, który wywłaszczył wątek. Ten proces nie musi być taki, który był wykonywany przez cały czas, kiedy proces został wywłaszczone, ale zawiera wskazówkę na temat tego, co spowodowało powstanie presji wywłaszczania na proces.

  • Oceń, w jaki sposób proces określa odpowiednią liczbę wątków do wykonania w tej fazie pracy. Jeśli proces oblicza bezpośrednio liczbę aktywnych wątków równoległych, rozważ zmodyfikowanie tego algorytmu, aby lepiej uwzględnić liczbę dostępnych rdzeni logicznych w systemie. Jeśli używasz środowiska uruchomieniowego współbieżności, biblioteki równoległej zadań lub PLINQ, te biblioteki wykonują pracę obliczania liczby wątków.

Nieefektywne we/wy

Inefficient I/O

Nadmierne użycie operacji we/wy jest częstą przyczyną nieefektywności w aplikacjach. Rozważmy poprzednią ilustrację. Profil widocznej osi czasu pokazuje, że 44 procent widocznego czasu wątku jest używane przez we/wy. Oś czasu przedstawia duże ilości operacji we/wy, co wskazuje, że profilowana aplikacja jest często blokowana przez we/wy. Aby wyświetlić szczegółowe informacje na temat rodzajów operacji we/wy i miejsca zablokowania programu, powiększ problematyczne regiony, sprawdź profil widocznej osi czasu, a następnie kliknij określony blok We/Wy, aby wyświetlić bieżące stosy wywołań.

Blokowanie konwojów

Lock convoys

Konwoje blokady występują, gdy aplikacja uzyskuje blokady w kolejności pierwszej, pierwszej obsługi, a gdy wskaźnik przylotu w blokadzie jest wyższy niż stopa pozyskiwania. Połączenie tych dwóch warunków powoduje, że żądania blokady mogą rozpocząć tworzenie kopii zapasowej. Jednym ze sposobów zwalczania tego problemu jest użycie "niesprawiedliwych" blokad lub blokad, które dają dostęp do pierwszego wątku, aby znaleźć je w odblokowanych stanach. Na poprzedniej ilustracji przedstawiono to zachowanie konwoju. Aby rozwiązać ten problem, spróbuj zmniejszyć rywalizację o obiekty synchronizacji i spróbować użyć nieuczciwych blokad.

Widok wątków