Profilowanie (programowanie komputerowe) - Profiling (computer programming)
Rozwój oprogramowania |
---|
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
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 gprof
rozszerzono 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 gprof
i 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ż
- Wydajność algorytmiczna
- Reper
- Wydajność Javy
- Lista narzędzi do analizy wydajności
- PAPI to przenośny interfejs (w postaci biblioteki) do liczników wydajności sprzętu na nowoczesnych mikroprocesorach.
- Inżynieria wydajności
- Przewidywanie wydajności
- Podnoszenie wydajności
- Weryfikacja czasu wykonywania
- Optymalizacja pod kątem profilu
- Statyczna analiza kodu
- Archeologia oprogramowania
- Czas realizacji najgorszego przypadku (WCET)
Bibliografia
Linki zewnętrzne
- Artykuł „ Potrzeba szybkości — eliminowanie wąskich gardeł wydajności ” dotyczący przeprowadzania analizy czasu wykonywania aplikacji Java przy użyciu produktu IBM Rational Application Developer .
- Profilowanie kodu wygenerowanego i zinterpretowanego w czasie wykonywania przy użyciu analizatora wydajności VTune