Profilowanie (programowanie komputerowe) - Profiling (computer programming)

W inżynierii oprogramowania , profilowanie ( „Program profilowania”, „oprogramowanie profilowania”) jest formą dynamicznej analizy programu , że środki, na przykład, przestrzeń (pamięć) lub czas złożoność programu The korzystanie z poszczególnych instrukcji , lub częstotliwość i czas trwania wywołań funkcji. Najczęściej informacje profilowane służą do wspomagania optymalizacji programów , a dokładniej inżynierii wydajności .

Profilowanie jest osiągane przez instrumentację kodu źródłowego programu lub jego binarnej postaci wykonywalnej przy użyciu narzędzia o nazwie profiler (lub profiler kodu ). Programiści mogą korzystać z wielu różnych technik, takich jak metody oparte na zdarzeniach, statystyczne, instrumentalne i symulacyjne.

Zbieranie wydarzeń programowych

Profilerzy używają szerokiej gamy technik do zbierania danych, w tym przerwań sprzętowych , instrumentacji kodu , symulacji zestawu instrukcji , zaczepów systemu operacyjnego i liczników wydajności .

Korzystanie z profilerów

Graficzne wyjście profilera CodeAnalyst .

Narzędzia do analizy programu są niezwykle ważne dla zrozumienia zachowania programu. Architekci komputerowi potrzebują takich narzędzi do oceny wydajności programów na nowych architekturach . Twórcy oprogramowania potrzebują narzędzi do analizy swoich programów i identyfikowania krytycznych sekcji kodu. Twórcy kompilatorów często używają takich narzędzi, aby dowiedzieć się, jak dobrze działa ich algorytm planowania instrukcji lub przewidywania rozgałęzień ...

—  ATOM, PLDI , '94'

Dane wyjściowe profilera mogą być:

  • Statystyczne podsumowanie zaobserwowanych zdarzeń ( profil )
Podsumowanie informacji o profilu jest często przedstawiane z adnotacjami względem instrukcji kodu źródłowego, w których występują zdarzenia, więc rozmiar danych pomiarowych jest liniowy do rozmiaru kodu programu.
/* ------------ source------------------------- count */             
0001             IF X = "A"                     0055
0002                THEN DO                       
0003                  ADD 1 to XCOUNT           0032
0004                ELSE
0005             IF X = "B"                     0055
  • Strumień zarejestrowanych zdarzeń ( ślad )
W przypadku programów sekwencyjnych zwykle wystarcza profil podsumowania, ale problemy z wydajnością w programach równoległych (oczekiwanie na komunikaty lub problemy z synchronizacją) często zależą od relacji czasowych zdarzeń, co wymaga pełnego śledzenia, aby zrozumieć, co się dzieje.
Rozmiar (pełnego) śladu jest liniowy do długości ścieżki instrukcji programu , co czyni go nieco niepraktycznym. Śledzenie może zatem zostać zainicjowane w jednym punkcie programu i zakończone w innym punkcie, aby ograniczyć wydajność.
  • Ciągła interakcja z hiperwizorem (na przykład ciągłe lub okresowe monitorowanie za pomocą wyświetlacza ekranowego)
Daje to możliwość włączenia lub wyłączenia śledzenia w dowolnym momencie podczas wykonywania, oprócz wyświetlania bieżących metryk dotyczących (wciąż wykonywanego) programu. Daje również możliwość zawieszenia procesów asynchronicznych w krytycznych punktach w celu bardziej szczegółowego zbadania interakcji z innymi równoległymi procesami.

Profiler można zastosować do pojedynczej metody lub w skali modułu lub programu w celu zidentyfikowania wąskich gardeł wydajności, dzięki czemu długotrwały kod jest oczywisty. Profiler może służyć do zrozumienia kodu z punktu widzenia czasu w celu zoptymalizowania go do obsługi różnych warunków środowiska uruchomieniowego lub różnych obciążeń. Wyniki profilowania mogą być pozyskiwane przez kompilator, który zapewnia optymalizację sterowaną profilem . Wyniki profilowania można wykorzystać do kierowania projektowaniem i optymalizacją indywidualnego algorytmu; algorytm dopasowywania symbole wieloznaczne Krauss przykład. Profilery są wbudowane w niektóre systemy zarządzania wydajnością aplikacji , które agregują dane profilowania, aby zapewnić wgląd w obciążenia transakcji w aplikacjach rozproszonych .

Historia

Narzędzia do analizy wydajności istniały na platformach IBM/360 i IBM/370 od wczesnych lat siedemdziesiątych, zwykle oparte na przerwaniach czasowych, które rejestrowały słowo statusu programu (PSW) w ustalonych interwałach czasowych w celu wykrycia „gorących punktów” w wykonywanym kodzie. Był to wczesny przykład pobierania próbek (patrz poniżej). Na początku 1974 r. symulatory zestawów instrukcji umożliwiły pełne śledzenie i inne funkcje monitorowania wydajności.

Analiza programów oparta na profilerach w systemie Unix sięga roku 1973, kiedy systemy uniksowe zawierały podstawowe narzędzie prof, które wymieniało każdą funkcję i czas jej wykonywania. W 1982 roku gprofrozszerzono koncepcję o kompletną analizę wykresów połączeń .

W 1994 roku Amitabh Srivastava i Alan Eustace z Digital Equipment Corporation opublikowali artykuł opisujący ATOM (Analysis Tools with OM). Platforma ATOM konwertuje program do własnego profilera: w czasie kompilacji wstawia kod do programu do analizy. Wstawiony kod generuje dane analityczne. Ta technika – modyfikowanie programu w celu jego analizy – jest znana jako „ oprzyrządowanie ”.

W 2004 roku zarówno gazeta, jak gprofi ATOM znalazły się na liście 50 najbardziej wpływowych gazet PLDI w okresie 20-letnim kończącym się w 1999 roku.

Typy profili na podstawie danych wyjściowych

Profiler płaski

Płaskie profilery obliczają średnie czasy połączeń z połączeń i nie dzielą czasów połączeń na podstawie odbiorcy lub kontekstu.

Profiler wykresu wywołań

Profilery wykresu połączeń pokazują czasy połączeń i częstotliwości funkcji, a także zaangażowane łańcuchy połączeń na podstawie wywoływanego. W niektórych narzędziach nie jest zachowywany pełny kontekst.

Profiler wrażliwy na dane wejściowe

Profilery wrażliwe na dane wejściowe dodają kolejny wymiar do profilerów płaskich lub wykresów wywoławczych, wiążąc miary wydajności z funkcjami obciążeń wejściowych, takimi jak rozmiar wejściowy lub wartości wejściowe. Generują wykresy, które charakteryzują skalowanie wydajności aplikacji w zależności od jej danych wejściowych.

Szczegółowość danych w typach profilera

Profilery, które same są programami, analizują programy docelowe, zbierając informacje o ich wykonaniu. Na podstawie szczegółowości danych i sposobu, w jaki profilery zbierają informacje, są one klasyfikowane jako profilery oparte na zdarzeniach lub statystyczne. Profilery przerywają wykonywanie programu w celu zebrania informacji, co może skutkować ograniczoną rozdzielczością pomiarów czasu, co należy podjąć z przymrużeniem oka. Podstawowe profilery blokowe zgłaszają liczbę cykli zegarowych maszyny poświęconych na wykonanie każdego wiersza kodu lub czas oparty na dodaniu ich razem; czasy raportowane na blok podstawowy mogą nie odzwierciedlać różnicy między trafieniami i chybieniem w pamięci podręcznej .

Profilery oparte na zdarzeniach

Wymienione tutaj języki programowania mają profilery oparte na zdarzeniach:

  • Java : interfejs API JVMTI (JVM Tools Interface), dawniej JVMPI (JVM Profiling Interface), udostępnia zaczepy dla profilerów do przechwytywania zdarzeń, takich jak wywołania, ładowanie klas, rozładowywanie, wprowadzanie wątków i opuszczanie.
  • .NET : można dołączyć agenta profilowania jako serwer COM do środowiska CLR za pomocą interfejsu API profilowania . Podobnie jak Java, środowisko wykonawcze udostępnia następnie agentowi różne wywołania zwrotne, służące do przechwytywania zdarzeń, takich jak metoda JIT /enter/wyjście, tworzenie obiektów itp. Szczególnie wydajny, ponieważ agent profilowania może przepisać kod bajtowy aplikacji docelowej w dowolny sposób.
  • Python : Profilowanie Pythona obejmuje moduł profile, hotshot (który jest oparty na wykresie wywołań) i użycie funkcji 'sys.setprofile' do przechwytywania zdarzeń takich jak c_{call,return,exception}, python_{call,return,exception}.
  • Ruby : Ruby używa również podobnego interfejsu do Pythona do profilowania. Flat-profiler w profile.rb, module i ruby-prof oraz C-extension są obecne.

Profile statystyczne

Niektóre profilery działają na zasadzie próbkowania . Profiler próbkowania sonduje stos wywołań programu docelowego w regularnych odstępach czasu przy użyciu przerwań systemu operacyjnego . Profile próbkowania są zazwyczaj mniej dokładne i precyzyjne pod względem liczbowym, ale umożliwiają programowi docelowemu działanie z prawie pełną prędkością.

Uzyskane dane nie są dokładne, ale są przybliżeniem statystycznym. „Rzeczywista wielkość błędu to zwykle więcej niż jeden okres próbkowania. W rzeczywistości, jeśli wartość jest n razy większa od okresu próbkowania, oczekiwany błąd jest pierwiastkiem kwadratowym z n okresów próbkowania”.

W praktyce profilery próbkowania mogą często zapewnić dokładniejszy obraz wykonania programu docelowego niż inne podejścia, ponieważ nie są tak inwazyjne dla programu docelowego, a zatem nie mają tak wielu skutków ubocznych (takich jak pamięć podręczna lub instrukcje dekodowanie potoków). Ponadto, ponieważ nie wpływają one tak bardzo na szybkość wykonywania, mogą wykrywać problemy, które w przeciwnym razie byłyby ukryte. Są również stosunkowo odporne na przeszacowanie kosztów małych, często nazywanych procedurami lub „ciasnymi” pętlami. Mogą pokazywać względną ilość czasu spędzonego w trybie użytkownika w porównaniu z przerywanym trybem jądra, takim jak przetwarzanie wywołań systemowych .

Mimo to kod jądra do obsługi przerwań pociąga za sobą niewielką utratę cykli procesora, nieprawidłowe wykorzystanie pamięci podręcznej i nie jest w stanie rozróżnić różnych zadań występujących w nieprzerywalnym kodzie jądra (aktywność w zakresie mikrosekund).

Dedykowany sprzęt może wyjść poza to: ARM Cortex-M3 i niektóre najnowsze procesory MIPS Interfejs JTAG mają rejestr PCSAMPLE, który sampluje licznik programu w naprawdę niewykrywalny sposób, umożliwiając nieinwazyjne zbieranie płaskiego profilu.

Niektóre powszechnie stosowane do profilowania statystyczne dla Java / kodu zarządzanego są SmartBear Software 's AQtime i Microsoft ' s CLR Profiler . Profilery te obsługują również profilowanie kodu natywnego, wraz z Apple Inc. „s Shark (OSX), oprofile (Linux), Intel VTune i równolegle wzmacniacz (część Intel Parallel Studio ) oraz Oracle pracę analizatora , między innymi.

Oprzyrządowanie

Ta technika skutecznie dodaje instrukcje do programu docelowego w celu zebrania wymaganych informacji. Należy pamiętać, że oprzyrządowanie programu może powodować zmiany wydajności, aw niektórych przypadkach może prowadzić do niedokładnych wyników i/lub błędów heisenbug . Efekt będzie zależał od tego, jakie informacje są gromadzone, od poziomu raportowanych szczegółów taktowania oraz od tego, czy podstawowe profilowanie bloków jest używane w połączeniu z oprzyrządowaniem. Na przykład dodanie kodu do zliczania każdego wywołania procedury/procedury prawdopodobnie przyniesie mniejszy efekt niż zliczanie, ile razy każda instrukcja jest przestrzegana. Kilka komputerów ma specjalny sprzęt do zbierania informacji; w tym przypadku wpływ na program jest minimalny.

Instrumentacja jest kluczem do określenia poziomu kontroli i ilości rozdzielczości czasowej dostępnej dla profilerów.

  • Ręczny : Wykonywany przez programistę, np. przez dodanie instrukcji do jawnego obliczania czasów wykonywania, po prostu zliczaj zdarzenia lub wywołania interfejsów API pomiarowych, takich jak standard Application Response Measurement .
  • Automatyczny poziom źródłowy : oprzyrządowanie dodane do kodu źródłowego przez automatyczne narzędzie zgodnie z polityką oprzyrządowania.
  • Język pośredni : oprzyrządowanie dodane do asemblera lub dekompilowanego kodu bajtowego, zapewniające obsługę wielu języków źródłowych wyższego poziomu i unikanie (niesymbolicznych) problemów z ponownym zapisaniem offsetu binarnego.
  • Wspomagany kompilator
  • Tłumaczenie binarne : Narzędzie dodaje instrumentację do skompilowanego pliku wykonywalnego .
  • Instrumentacja środowiska uruchomieniowego : bezpośrednio przed wykonaniem kod jest instrumentowany. Przebieg programu jest w pełni nadzorowany i kontrolowany przez narzędzie.
  • Wstrzykiwanie w czasie wykonywania: lżejsze niż oprzyrządowanie w czasie wykonywania. Kod jest modyfikowany w czasie wykonywania, aby umożliwiał przeskoki do funkcji pomocniczych.

Oprzyrządowanie tłumacza

  • Opcje debugowania interpretera mogą umożliwić zbieranie metryk wydajności, gdy interpreter napotka każdą instrukcję docelową. A kodu bajtowego , stół kontrola lub JIT tłumacze są trzy przykłady, które zwykle mają pełną kontrolę nad wykonaniem kodu docelowego, umożliwiając niezwykle wszechstronne możliwości zbierania danych.

Hypervisor/Symulator

  • Hypervisor : Dane są gromadzone przez uruchomienie (zwykle) niezmodyfikowanego programu pod hypervisorem . Przykład: SIMMON
  • Symulator i hiperwizor : Dane zbierane interaktywnie i selektywnie przez uruchomienie niezmodyfikowanego programu w symulatorze zestawu instrukcji .

Zobacz też

Bibliografia

Linki zewnętrzne