FunkcjeCennikDokumentacjaBlog
Pobierz mote
← Blog
Technika·5 lipca 2026·3 min czytania

Dlaczego pisanie nie zwalnia nawet w długich dokumentach

Przy krótkich notatkach każdy edytor jest szybki. Różnica pojawia się, gdy dokument staje się długi, a decyduje o niej to, czy koszt pojedynczego naciśnięcia klawisza rośnie wraz z rozmiarem edycji, czy z rozmiarem dokumentu.

m
mote
Dwa pomiary wykonane po wprowadzeniu 300 znaków do dokumentu o rozmiarze 100 KB. Osobno mierzony jest moment, w którym rdzeń kończy edycję, ponowne parsowanie i dekorowanie (p95 0,44 ms), oraz moment, w którym wynik pojawia się na ekranie (p95 3,32 ms).
Dwa pomiary wykonane po wprowadzeniu 300 znaków do dokumentu o rozmiarze 100 KB. Osobno mierzony jest moment, w którym rdzeń kończy edycję, ponowne parsowanie i dekorowanie (p95 0,44 ms), oraz moment, w którym wynik pojawia się na ekranie (p95 3,32 ms).

Krótkie notatki pisze się szybko w każdym edytorze. Różnica ujawnia się, gdy dokument staje się długi.

Jeśli po każdym naciśnięciu klawisza edytor ponownie odczytuje cały dokument i od nowa rozmieszcza wszystko na ekranie, wprowadzanie tekstu zwalnia wraz ze wzrostem długości dokumentu. Dlatego edytor, który dobrze radził sobie z dziesięciowierszową notatką, staje się uciążliwy przy dokumencie projektowym liczącym dwa tysiące wierszy.

mote nie potraktował tego problemu jako kwestii wydajności, którą można naprawić później. Od początku uznał go za zasadę projektową, której trzeba przestrzegać.

Podczas edycji ponownie odczytywany i rozmieszczany jest tylko zmieniony zakres. Cały dokument jest odczytywany ponownie wyłącznie podczas otwierania pliku.

Ponownie odczytujemy tylko zmienione miejsca

W Markdownie wcześniejszy wiersz może zmienić znaczenie późniejszego. Jeśli w górnej części dokumentu zostanie otwarty blok kodu, cała treść poniżej może stać się kodem, a to samo zdanie może być interpretowane inaczej wewnątrz listy lub cytatu.

Dlatego mote zapamiętuje „bezpieczne punkty”, w których wpływ wcześniejszej treści na pewno się kończy. Gdy następuje edycja, rozpoczyna odczytywanie od najbliższego bezpiecznego punktu i zatrzymuje się w chwili, gdy treść ponownie się stabilizuje.

Bloki znajdujące się dalej nie są ponownie odczytywane. Jeśli liczba wierszy wzrosła lub zmalała, zmieniane jest tylko ich położenie. Dzięki temu koszt zależy nie od rozmiaru całego dokumentu, lecz od zakresu, który faktycznie się zmienił.

Parser stosuje wierszowy algorytm CommonMark i przechodzi wszystkie 652 testy specyfikacji. Przetwarzanie przyrostowe łatwo jednak może dawać po cichu błędne wyniki. Dlatego do losowych dokumentów stosujemy 3 600 losowych edycji, a następnie za każdym razem porównujemy wynik z rezultatem ponownego odczytania całego dokumentu.

Ten test wykrył również prawdziwy błąd. Występował on wtedy, gdy bezpieczny punkt dokładnie pokrywał się z edytowanym wierszem.

Zasad wydajności pilnują testy

Celem jest zakończenie przetwarzania przez rdzeń w czasie p95 wynoszącym 4 ms od naciśnięcia klawisza. Przekroczenie tego czasu traktujemy nie jako zadanie optymalizacyjne, lecz jako błąd.

Nie ograniczyliśmy się też do zapisania tej reguły w dokumentacji. Automatyczny test sprawdza, czy pełne ponowne parsowanie jest używane wyłącznie podczas otwierania pliku. Zapobiega również cyklicznemu uruchamianiu liczników czasu i zadań związanych z klatkami, gdy program jest bezczynny.

Wydajności także nie ocenia człowiek na oko. Stanowisko testowe wprowadza znaki na rzeczywistym ekranie i mierzy rozkład czasów przetwarzania. Zamiast średniej lub mediany analizujemy p95. Dzieje się tak dlatego, że użytkownika frustruje nie zwykła szybkość działania, lecz sporadycznie występujące długie opóźnienia.

Do pomiarów zawsze używamy tego samego, niezmiennego dokumentu.

Dokument doc100k.md używany przez stanowisko testowe, otwarty w trybie na żywo. W wierszu stanu widnieje 96 513 znaków oraz czas czytania wynoszący 103 minuty.
Dokument doc100k.md używany przez stanowisko testowe, otwarty w trybie na żywo. W wierszu stanu widnieje 96 513 znaków oraz czas czytania wynoszący 103 minuty.

Ekran także zmieniamy tylko w niezbędnym zakresie

Samo przejście na przyrostowe działanie parsera nie wystarczyło.

Podświetlanie składni w blokach kodu po każdej edycji ponownie przetwarzało wszystkie bloki. Była to ostatnia operacja, która zwalniała wraz ze wzrostem długości dokumentu niezależnie od rozmiaru edycji.

Teraz podświetlanie składni w niezmodyfikowanych blokach jest ponownie wykorzystywane bez zmian. Bloki znajdujące się za edytowanym miejscem są jedynie przesuwane o tyle, o ile zmieniła się liczba wierszy.

Bloki poza ekranem nie są rozmieszczane. Aby zachować szybkość również w długich dokumentach, trzeba ograniczyć zarówno zakres ponownego odczytywania, jak i zakres ponownego rysowania.

Są też wyjątki

Czasami trzeba ponownie przetworzyć cały dokument.

Dzieje się tak podczas otwierania pliku lub zmiany formatu zakończeń wierszy. Zmiana definicji odwołania do odnośnika może wpłynąć na dowolny odnośnik w całym dokumencie, dlatego zakres odświeżania ekranu również rozszerza się wtedy na cały dokument.

Nawet jeśli rdzeń działa szybko, ekran musi zaczekać na następną klatkę. W przypadku ekranu 60 Hz ograniczeniem staje się sam odstęp między klatkami. Dlatego osobno mierzymy czas przetwarzania przez rdzeń oraz czas do rzeczywistego pojawienia się wyniku na ekranie i nie umieszczamy tych dwóch wartości na jednej osi. Właśnie dlatego na okładce widnieją dwie różne linie.

Szybki edytor nie jest edytorem, który robi wszystko szybko.

To edytor, który nie wykonuje pracy, której nie musi wykonywać.

← StarszeDlaczego zamiast samodzielnie renderować znaki, powierzyliśmy to platformieNowsze →Ustaliliśmy reguły klawisza Enter, aby akapity wyglądały tak samo także w innych narzędziach
Bądź na bieżąco przez RSS.
Nic poza pisaniem.
Polski
© 2026 mote