PowerShell ISE na sterydach (2.0), część 5
W cyklu życia skryptu nierzadko zdarza się, że wraca on na biurko autora: czy to w celu usunięcia błędów, czy optymalizacji. W wersjach dostępnych do tej pory ISESteroids nieznacznie tylko usprawniał ten aspekt edytowania skryptów. Wersja dostępna obecnie (RC, do pobrania w tym samym miejscu, co wersje poprzednie) dodała jednak całą gamę elementów, które operacje z tego zakresu powinny usprawnić. Elementy te bazują na dodanej w wersji 2.0.12.5 “marginesie debuggera”. Więc choć początkowo planowałem w tej części zająć się “wisienką na torcie” – wszelkiego rodzaju wodotryskami, które ISESteroids dodaje, to temat ten musi chwilkę poczekać. Najpierw to, co istotne: odrobaczanie.
Na marginesie…
Zanim przejdziemy do konkretnych rozwiązań, zacznijmy od samego początku: margines debuggowania. Jest to jedna z opcji, które dostępne są wyłącznie w ramach ISESteroids. W ostatniej wersji wszystkie dodatkowe elementy możemy w bardzo wygodny sposób kontrolować: wystarczy kliknąć prawym przyciskiem na marginesie i włączyć/ wyłączyć interesujące nas opcje:
Margines debuggowania oznaczony jest (domyślnie) ciemno-szarym kolorem, który zmienia się w momencie analizowania skryptu. Dodatkowo wszelkie breakpointy oraz linia, w której aktualnie się znajdujemy, zostaną odpowiednio oznaczone:
Na belce też odnajdziemy informacje o błędach, zarówno poważniejszych (błędy w składni) jak i potencjalnych naruszeniach “dobrych praktyk” (jak wykorzystywanie aliasów):
Tyle odnośnie marginesu, pora przystąpić do debuggowania. Zanim jednak zaczniemy “odrobaczać” nasz skrypt, musimy go odpowiednio do tego przygotować.
Nie łam się!
PowerShell oferował całkiem solidne wsparcie dla “odrobaczania” od wersji drugiej, włącznie z dość rozbudowanym systemem breakpointów, jednak w ISE dostępny był tylko jeden z nich: przerywający działanie skryptu w wyznaczonej linii. ISESteroids nie pozbawia nas tej możliwości, dodaje jednak opcję, której w oryginale brakuje: przerywanie działania skryptu w sytuacji, gdy wykonana zostanie operacja na jednej ze zmiennych. Ustawienia dla tych breakpointów znajdziemy klikając prawym przyciskiem na wspomnianym wcześniej marginesie debuggera:
Wypada wspomnieć o tym, że jest to jedynie wyciągnięcie na powierzchnię funkcjonalności, do której dostęp mamy z poziomu konsoli. Również dodane w ten sposób breakpointy możemy w prosty sposób wyświetlić/ włączyć/ wyłączyć/ usunąć, korzystając przy tym poleceń *-PSBreakpoint:
Get-PSBreakpoint -Variable name | Disable-PSBreakpoint Get-PSBreakpoint -Variable name | Format-List Remove-PSBreakpoint -Id 16
Uruchomiając tych kilka poleceń uzyskamy efekt zgodny z oczekiwaniami:
Mniej istotna, choć bardzo ułatwiająca sam proces debugowania, jest rozbudowana narzędziówka, która dodatkowo w trakcie zatrzymania skryptu na jakimś breakpoincie sygnalizuje ten fakt “mrugającym” przyciskiem “stop”. Mamy też przyciski do ustawienia breakpointów i poszczególnych operacji dostępnych w trakcie “odrobaczania” (czyli trzech rodzajów “kroków”).
Dzięki takim usprawnieniom wyłapanie błędów w logice skryptu nie powinno stanowić problemu. Nie zawsze jednak do wprowadzenia poprawek skłaniają nas błędy. Bywa też tak, że skrypt działa poprawnie, ale zdecydowanie wolniej niż byśmy oczekiwali/ potrzebowali. W takim wypadku przyda nam się wsparcie innego elementu dodanego w ostatniej wersji ISESteroids.
Wąskie gardło
Stwierdzenie “skrypt wolno działa” jest na ogół równie pomocne dla osoby mającej wprowadzić w nim poprawki, mające na celu poprawę wydajności, jak sławetne “autobus się zepsuł”. Bywa tak, że mamy pewne przeczucia: która część pochłania najwięcej czasu. Ale czasem przypuszczenia bywają błędne, poprawiamy pracowicie jakiś fragment kodu i finalnie uzyskujemy efekt żaden, lub w skali działania całego skryptu – niezauważalny. W takich sytuacjach przydaje się narzędzie, które potrafi określić dokładnie, które elementy skryptu działają szybciej, a których uruchomienie trwa dłużej. ISESteroids oferowało ogólną informację o tym ile zajęła dana czynność już wcześniej, ale w ostatniej wersji możemy już dokładnie prześledzić szybkość działania poszczególnych fragmentów naszego skryptu przy pomocy wbudowanego narzędzia do analizy szybkości działania kodu. Uruchamiamy go również z poziomu marginesu do debuggowania. Możemy przy tym zdecydować, czy chcemy go uruchamiać dla wszystkich skryptów, czy jedynie dla aktualnie analizowanego:
Wyniki prezentowane są w bardzo przejrzysty sposób: po uruchomieniu badanego skryptu czas działania poszczególnych jego składowych (bądź częstotliwość wywołania danej linii, jeśli zdecydujemy się na tę opcję) zostanie przedstawiony w postaci wykresu, którego oś współrzędnych pokrywa się z marginesem, oś rzędnych z liniami naszego kodu. Przez to od razu widać, która linia pochłania najwięcej czasu:
Wykres dla częstotliwości wygląda nieco inaczej. Pozwala wyłapać elementy, które być może wywoływane są częściej, niż się spodziewaliśmy:
Pierwsza pozwala łatwo ocenić, które części skryptu pochłaniają najwięcej czasu i dzięki temu wprowadzić poprawki, które faktycznie mogą skrócić działanie naszego skryptu. Z drugiej strony, nawet jeśli fragment kodu pozwala na niewielkie poprawki, ale jest wywoływany bardzo często, to na koniec zysk może być również zauważalny. Obie statystyki mogą więc zastąpić “skrypt działa wolno” bardzo konkretnym “optymalizacja w linii 30 i 55 znacznie przyspieszy działanie skryptu”. Oczywiście, nie zawsze poprawki są proste, ale przynajmniej wiemy w którym miejscu warto zainwestować nasz czas.