Tworząc oprogramowanie należy pamiętać o wydajności. Od aplikacji wymaga się płynnego działania, informacji o zmianie postępu, reakcji na działania użytkownika, itp. W przypadku platform mobilnych problem ten jest jeszcze bardziej poważny. Przyzwyczailiśmy się już, że komputery posiadają wydajne kilku rdzeniowe procesory, dużą ilość pamięci operacyjnej, czy szybki dysk. To co kiedyś było ważne w trakcie wytwarzania oprogramowania – efektywność zaproponowanych rozwiązań – teraz niejednokrotnie nie jest brane pod uwagę. Obecnie, niedociągnięcia w kodzie rekompensowane są poprzez wydajny sprzęt.

Trochę inaczej sytuacja ma się w przypadku Windows Phone. Ponieważ jest to platforma mobilna, która korzysta z zasilania bateryjnego, to jej zasoby są ograniczone. Po pierwsze mamy słabszy procesor, ograniczoną ilość pamięci oraz miejsca na dane. Dodatkowo Microsoft nakłada na aplikację szereg ograniczeń i wymagań. Niektóre z nich to:

  • wyświetlenie pierwszego ekranu w ciągu 5 sekund od uruchomienia aplikacji,
  • aplikacja powinna być w stanie reagować na akcje użytkownika w ciągu 20 sekund od uruchomienia aplikacji,
  • aplikacja nie powinna zajmować więcej niż 90 MB pamięci w przypadku urządzeń, które mają mniej niż 256 MB pamięci wbudowanej,
  • itp.

Więcej szczegółów można znaleźć na stronie – Application Certification Requirements for Windows Phone.

Na całe szczęście Microsoft nie zostawia użytkownika samego i dostarcza za darmo narzędzia, które pozwalają na zdiagnozowanie problemów z wydajnością. Do dyspozycji programisty zostały oddane dwa narzędzia:

  • profiler,
  • mierniki wydajności.

Pierwsze z nich – profiler – umożliwia „nagranie” działania aplikacji. Dane zbierane są w dwóch trybach. W zależności od decyzji użytkownika, uzyska on dane o wydajności aplikacji analizując elementy odpowiedzialne za wyświetlanie aplikacji oraz wywoływanie poszczególnych metod w kodzie. Drugą opcją jest sprawdzenie wydajności analizując zużycie pamięci. Microsoft zaleca używanie pierwszej opcji, chyba, że pojawią się jakieś problemy z pamięcią.

Wydaje mi się, że nie ma sensu dalej się zagłębiać w ten temat ponieważ Maciej przygotował ciekawe demo tego narzędzia na Channel9.

Drugim elementem pozwalającym na bieżące śledzenie wydajności są liczniki, które pokazują się na telefonie w momencie, gdy program działa w trybie debug.

Windows Phone Mierniki Wydajności

Composition Thread Frame Rate

Określa ilość klatek na sekundę wyświetlanych przez wątek kompozytora (composition thread). W ramach tego wątku realizowane są takie operacje jak: skalowanie, proste transformacje, przycinanie, obroty, itp. W przypadku aplikacji na Windows Phone za wartość optymalną uznaje się co najmniej 45 klatek na sekundę. Mniejsze wartości są też czasem tolerowane, jednakże w sytuacji spadku poniże 30 należy pomyśleć nad optymalizacją. W takiej sytuacji licznik ten zmieni kolor na czerwony.

Dość często może zdarzyć się, że wskaźnik ten przyjmie wartość 0. W momencie, gdy nasz ekran jest statyczny i nic się na nim nie zmienia jest to sytuacja normalna i nie należy się nią przejmować.

UI Thread Frame Rate

Licznik ten informuje nas o ilości klatek na sekundę generowanych przez wątek UI. Do jego zadań należą:

  • obsługa animacji, które nie mogą zostać obsłużone przez wątek kompozytora,
  • wykonanie wszelkich operacji wymagających dostępu do elementów UI (np. data binding),
  • wykonanie kodu umieszczonego w elementach związanych z UI (np. obsługa zdarzeń).

Wartość tego licznika z reguły nie jest większa od Composition Thread Frame Rate. Nie powinna również spadać poniżej 15 klatek na sekundę. Kiedy to się dzieje to licznik zmienia kolor na czerwony. Wartość typowa to co najmniej 30 klatek na sekundę. Im większa jest wartość tego licznika tym aplikacja lepiej odpowiada na zachowania użytkownika.

Interpretacja wartości 0 jest analogiczna do poprzedniego przypadku.

Texture Memory Usage

Informuje o ilości pamięci zajmowanej przez tekstury wykorzystywane w programie. Nie jest to natomiast licznik zużycia pamięci przez program.

Licznik ten nie ma ustalonych limitów oraz wartości optymalnych. Dwa pierwsze wskaźniki zachowują się w porządku to nie należy się przejmować tym wskaźnikiem.

Surface Counter i Intermediate Surface Counter

Kolejne dwa wskaźniki połączę w jeden punkt. W zasadzie nie znalazłem nigdzie rozsądnego zastosowanie tych dwóch wartości. Pierwsza z nich – Surface Counter – określa ilość powierzchni przekazanych do GPU w celu dalszego przetworzenia. Dokładniej mówiąc ilość powierzchni przesłanych z wątku UI do wątku kompozytora. Drugi natomiast wskaźnik – Intermediate Surface Counter – informuje nas ile zostało wygenerowanych powierzchni w wyniku działania wątku kompozytora.

Fill Rate Counter

Ostatni wskaźnik jest jednym z najbardziej kluczowych elementów informujących nas o wydajności aplikacji. Jego wartość oznacza ilość pikseli wygenerowanych w celu wyświetlenia danego ekranu. W tym przypadku wartość 1 oznacza cały ekran, czyli 480 * 800 pikseli. Zgodnie z zaleceniami wartość ta nie powinna przekraczać 2,5. W przypadku przekroczenia wartości 3 wskaźnik zmieni kolor na czerwony. Użytkownik zauważy znaczy spadek wydajności gdy wskaźnik ten przekroczy wartość 3,5.

Może na początku wydawać się dziwne, że do narysowania jednego ekranu potrzeba czasem wyznaczyć wartość jakiegoś piksela kilkukrotnie. Takie zachowanie ma miejsce przykładowo gdy na ekranie wyświetlanych jest kilka animacji lub obrazków wzajemnie na siebie się nakładających. W tym momencie obszary, które na siebie nachodzą są rysowane kilkukrotnie.

Dodatkowy narzut dodaje też zastosowanie przeźroczystości.

W celu optymalizacji tego wskaźnika należy zastanowić się na UI i pomyśleć, czy rzeczywiście wszystkie elementy powinny się na nim znaleźć. Może niektóre są zawsze przesłonięte i można je usunąć. Dodatkowo można również zastanowić się czy nie istnieją obrazki lub elementy graficzne, które można połączyć w jedną całość.

Tak jak zostało już to wcześniej wspomniane przedstawione liczniki dostępne są w trybie debug. Jeśli chcemy je użyć poza tym trybem to należy dodać do kodu następującą linijkę:

Application.Current.Host.Settings.EnableFrameRateCounter = true;

Pewnie nie jestem odosobnionym przypadkiem, który uważa, że wśród tych liczników brakuje jeszcze informacji o zużyciu pamięci. Ten brak można w bardzo prosty sposób samemu naprawić. Ale o tym kiedy indziej.

Na koniec jeszcze jedna mała uwaga. W przypadku emulatora Windows Phone 7 występuje bardzo dziwne, ale pozytywne zjawisko. Aplikacje testowane na emulatorze działają bardzo często wydajniej niż na telefonie. Z tego powodu wskazane jest przetestowanie aplikacji na telefonie przed wystaniem jej na MarketPlace.