La causa della pesantezza non era Markdown, ma il motore web
Se le ventole iniziano a girare mentre un editor Markdown è semplicemente aperto, non è perché Markdown sia oneroso. Misurando lo stesso documento nelle stesse condizioni, il costo deriva dal motore di rendering e da un ciclo legato al timer.

Ho lasciato aperto un editor Markdown sul portatile. Non stavo digitando nulla, ma le ventole hanno iniziato a girare.
All’inizio pensavo che fosse colpa di Markdown. Credevo che fosse lento perché continuava a ridisegnare il documento.
Era davvero così?
Li ho confrontati nelle stesse condizioni
Ho impostato le stesse dimensioni dello schermo, lo stesso metodo di rendering e lo stesso documento. Ho aperto un documento da 7,5 KB e 113 righe e non ho fatto nulla per 25 secondi. Anche durante la digitazione ho inserito gli stessi caratteri alla stessa velocità.
In stato di inattività, apostrophe, che disegna l’anteprima tramite un motore web, utilizzava il 34,6% della CPU e 378 MB di memoria. I processi erano cinque.
Il prototipo, che mostrava lo stesso documento in linea senza un motore web, utilizzava lo 0,7% della CPU e 64 MB di memoria. Il processo era uno solo.
Entrambi visualizzavano Markdown, ma i risultati erano molto diversi.
Disattivando soltanto l’anteprima in apostrophe, l’utilizzo della CPU è sceso al 7,0% e quello della memoria a 133 MB. L’app e il toolkit erano rimasti gli stessi. Era cambiato soltanto il modo in cui veniva disegnata l’anteprima.
Ho misurato anche un editor di testo che non visualizzava affatto Markdown. Utilizzava il 2,2% della CPU e 79 MB di memoria.
Il prototipo che visualizzava Markdown era addirittura più leggero.
A quel punto è diventato chiaro. Il problema non era Markdown.
Lavorava 60 volte al secondo anche quando non facevo nulla
La causa si trovava nel codice che sincronizzava lo scorrimento dell’anteprima con il testo.
Questo codice non veniva eseguito soltanto durante lo scorrimento. Ogni 16 ms un timer si attivava ed eseguiva JavaScript nel processo WebKit. Quando arrivava la risposta, impostava nuovamente il timer.
Lavorava circa 60 volte al secondo anche quando nessuno toccava la finestra.
Quando si usa un motore web, l’area in cui si modifica il documento e quella in cui viene disegnata l’anteprima diventano due mondi separati. Il modo più semplice per sincronizzare i due stati è controllarli continuamente. Se non si misura separatamente la CPU in stato di inattività, questo costo è difficile da notare.
Durante la digitazione la differenza è diventata ancora maggiore. apostrophe utilizzava il 180% della CPU, mentre il prototipo ne utilizzava il 41%.
Uno dei due, a ogni pressione di un tasto, comunicava persino con il processo del browser. L’altro applicava nuovamente i tag soltanto alle righe modificate.
Ho trasformato i risultati delle misurazioni in principi di progettazione
Il prototipo non aveva ottimizzazioni particolari.
Gli stili venivano applicati al testo tramite tag. Più modifiche venivano raggruppate in un’unica operazione idle monouso, che si eliminava da sola. L’applicazione dei tag era limitata alle righe modificate. Veniva utilizzato anche un solo processo.
Non avevo aggiunto qualcosa: avevo semplicemente evitato di includere ciò che non era necessario.
In seguito ho stabilito due principi di progettazione.
Primo, non includere un motore web tra le dipendenze.
Secondo, se il documento non cambia e non ci sono animazioni, non programmare frame, timer o tick.
È difficile applicare questi principi in un secondo momento. Un motore web non è una semplice libreria: cambia la struttura dell’app. Una volta introdotto, rimuoverlo equivale a ricostruire l’app. E senza una regola precisa, anche i timer finiscono per moltiplicarsi, uno per ogni funzionalità.
In cambio, ho dovuto rinunciare alla strada più facile. Non potevo controllare le modifiche ai file tramite polling e non potevo nemmeno affidare le formule a una webview. Ho dovuto realizzare direttamente il layout necessario.
Per evitare che questi principi perdano chiarezza, ripeto le misurazioni su un dispositivo reale a ogni rilascio.

Ci sono anche aspetti a cui prestare attenzione quando si osservano i numeri
L’esperimento è stato condotto con rendering software. L’utilizzo della CPU risulta più elevato rispetto a un ambiente con una GPU reale. Per questo bisogna considerare i rapporti, più che i valori assoluti.
Anche lo 0,7% di CPU in stato di inattività del prototipo era dovuto principalmente al lampeggiamento del cursore. Disattivandolo, il valore era difficilmente distinguibile da zero.
Questo non significa che tutte le app basate su un motore web abbiano lo stesso problema. Questi risultati si riferiscono esclusivamente ad apostrophe. Esistono anche motori, come quelli basati su Chromium, che riducono il lavoro in stato di inattività.
Nemmeno il prototipo aveva molte funzionalità. Non disponeva di tabelle, formule, esportazione o ricerca. Il confronto è possibile soltanto fino al costo del rendering.
Eppure una cosa era chiara.
A generare il costo non era Markdown. Erano il motore di rendering e un ciclo che non si fermava mai.
Quando si individua con precisione la causa, la leggerezza non diventa una nuova funzionalità, ma una sottrazione.