Jak sprawiliśmy, że otwarty, lecz bezczynny program nie zużywa procesora
Edytor jest otwarty przez cały dzień, ale faktyczne pisanie zajmuje tylko część tego czasu. Przez resztę czasu mote nie planuje ani klatek, ani timerów, a przestrzegania tej zasady pilnuje na dwóch poziomach — poprzez analizę kodu i pomiary na rzeczywistym sprzęcie.

Edytor jest aplikacją, która pozostaje otwarta na laptopie najdłużej. Jednak faktyczne pisanie nie zajmuje wiele czasu. Przez większość czasu edytor po prostu cicho pozostaje otwarty, gdy robimy coś innego.
Dlatego mote przyjął jedną zasadę.
Jeśli dokument się nie zmienia i nie ma żadnej animacji, nie rób nic.
Żadnych zaplanowanych klatek, powtarzających się timerów ani okresowego sprawdzania. To nie optymalizacja, lecz zasada projektowa, której należy przestrzegać przed wszystkimi innymi funkcjami.
Jeśli nic się nie dzieje, liczba klatek również wynosi 0
Na podstawie samego użycia CPU trudno stwierdzić, czy aplikacja zachowuje się spokojnie. Wartość zmienia się przy każdym pomiarze, a po zaokrągleniu łatwo staje się zerem.
Dlatego mote najpierw sprawdza liczbę klatek. Jeśli przez 10 sekund po wyświetleniu okna dokument się nie zmienia, liczba narysowanych klatek musi wynosić dokładnie 0. Są one liczone bezpośrednio wewnątrz aplikacji, a jeśli zostanie narysowana choć jedna, kod nie zostanie scalony.
Nawet 0 klatek nie daje jeszcze pewności. W niewidocznym miejscu wątki mogą nadal się wybudzać. Dlatego rejestrujemy również, ile razy na sekundę wybudzają się wszystkie wątki procesu. Ponieważ wciąż gromadzimy dane bazowe, sama ta wartość nie blokuje jeszcze prac programistycznych.
Jedynym wyjątkiem jest miganie kursora tekstowego. Nie używamy powtarzającego się timera; po jednym mignięciu ponownie planujemy następne działanie. Gdy okno traci fokus, miganie natychmiast się zatrzymuje. Budżet użycia CPU w stanie bezczynności, uwzględniający także kursor, wynosi 0,3%.
Nie analizujemy wydajności w stanie bezczynności w oderwaniu od reszty. Odkładając renderowanie, łatwo sprowadzić liczbę klatek do 0, ale wtedy wpisane znaki mogą pojawiać się z opóźnieniem. Dlatego jednocześnie sprawdzamy opóźnienie wprowadzania znaków, szybkość uruchamiania i pamięć. Jeśli choć jeden limit zostanie przekroczony, kod nie zostanie scalony.

Raz w kodzie, raz na rzeczywistym urządzeniu
Zasady z czasem się rozmywają. Dlatego sprawdzamy je dwukrotnie.
Najpierw sprawdzamy kod. Automatycznie wyszukujemy powtarzające się timery, niekończące się tyknięcia, odpytywanie polegające na ciągłym zasypianiu i wybudzaniu oraz kod, który niepotrzebnie ponownie odczytuje cały plik. Gdy coś takiego zostanie znalezione, CI zatrzymuje się w tym miejscu. Jeśli wyjątek jest naprawdę konieczny, bezpośrednio nad kodem trzeba wyjaśnić, dlaczego dane zadanie się kończy.
Następnie wykonujemy pomiar na rzeczywistym urządzeniu. Przestrzegamy przy tym czterech warunków.
Pomiar wykonujemy na rzeczywistym ekranie z GPU. Wskaźnik pozostawiamy poza oknem. Korzystamy z rzeczywistej magistrali sesji, a klatki liczymy dokładnie w chwili ich rysowania.
Warunki te powstały w wyniku napotkanych problemów. Zdarzyło się, że samo umieszczenie wskaźnika nad oknem spowodowało wygenerowanie 150 klatek w stanie bezczynności. W odizolowanej sesji uruchamianie opóźniało się o kilka sekund, ponieważ zestaw narzędzi czekał na odpowiedź. Gdy używaliśmy licznika zgłaszającego klatki z opóźnieniem, klatki ekranu startowego mieszały się czasem z okresem bezczynności.
Pamięci również nie oceniamy na podstawie wartości bezwzględnej. Pamięć zajmowana przez zestaw narzędzi i sterownik graficzny może różnić się o dziesiątki MB w zależności od środowiska.
Zamiast tego za punkt odniesienia przyjmujemy pusty dokument. Sprawdzamy wyłącznie, o ile więcej pamięci zużywa otwarcie dokumentu w porównaniu z pustym dokumentem. W ostatnim pomiarze pusty dokument zużywał 116 MB, a dokument o rozmiarze 100 KB — 120 MB. Dodatkowe zużycie pamięci przez mote wyniosło 4 MB, czyli mieściło się w budżecie 8 MB.
Nie mierzyliśmy tego w ten sposób od początku. Kiedyś wydawało nam się, że przekroczyliśmy budżet pamięci, ale okazało się, że wzrosło nie zużycie aplikacji, lecz bazowe zużycie pamięci przez środowisko uruchomieniowe. Od tamtego dnia zamiast wartości bezwzględnej mierzymy „to, ile dodała nasza funkcja”.

Podczas pracy programistycznej wyświetlamy również na ekranie liczbę aktywnych timerów. Jeśli nie wynosi 0, można to zauważyć jeszcze przed commitem.
Automatyczny zapis również przestrzega tej zasady. Timer ustawiamy tylko raz, gdy dokument się zmieni, i usuwamy go po zakończeniu zapisu. Nie wybudzamy aplikacji okresowo, by sprawdzić: „Czy coś się zmieniło?”.
To nie są liczby służące do pokonania konkurencji
Początkowo chcieliśmy przedstawiać wydajność w stanie bezczynności jako przewagę nad Typorą. Jednak bezpośrednie pomiary pokazały, że tak nie jest.
Na tym samym urządzeniu i w tych samych warunkach użycie CPU przez Typorę w stanie bezczynności wyniosło 0,1%. Było więc w praktyce takie samo jak w mote. Aplikacjami, dla których potwierdziliśmy różnicę, były Obsidian z wynikiem 0,8% i MarkText z wynikiem 0,6%.
Zdarzyło nam się również podać błędną informację. Przez pewien czas w dokumentacji widniało zdanie: „Typora zużywa CPU, gdy pozostaje otwarta”. Wartość 34,6%, na której oparto to stwierdzenie, była wynikiem pomiaru aplikacji apostrophe, a nie Typory. Po ponownym sprawdzeniu od razu poprawiliśmy to zdanie.
0 klatek w stanie bezczynności nie jest twierdzeniem wymierzonym w konkurencję. To dyscyplina, której mote sam przestrzega. Jeśli nie ma żadnych cyklicznie wykonywanych zadań, zawsze można wyjaśnić, co aplikacja robi w danej chwili.
Z powodu tej zasady z pewnych rzeczy również zrezygnowaliśmy
Często nie możemy skorzystać z wygodnego rozwiązania.
Zamiast okresowo sprawdzać, czy plik został zmieniony z zewnątrz, musimy odbierać powiadomienia o zmianach z systemu operacyjnego. Zamiast powierzyć formuły widokowi internetowemu, stworzyliśmy własny silnik układu. Animacje również nie mogą działać bez końca. Każdy ruch ma początek i koniec, a po zakończeniu musi całkowicie się zatrzymać.
Nie będziemy twierdzić, że bateria działa o kilka godzin dłużej. To liczba, której nie zmierzyliśmy. Sprawdziliśmy liczbę klatek, użycie CPU, a nawet liczbę wybudzeń wątków.
Nie robić nic, gdy nic się nie dzieje.
W mote nie jest to funkcja, lecz zasada, którą muszą spełnić wszystkie funkcje.