FunzioniPrezziDocumentazioneBlog
Ottieni mote
← Blog
Sviluppo·27 agosto 2026·6 min di lettura

Perché pubblichiamo i numeri invece di limitarci a dire che è leggero

Nell’affermazione che qualcosa è leggero non c’è nulla da verificare. mote ha fissato otto numeri con cui parlare di sé e pubblica insieme a essi il metodo e le condizioni di misurazione, nonché i dati grezzi.

m
mote
Memoria, CPU durante la digitazione e numero di processi delle quattro app, misurati sulla stessa macchina con lo stesso script. Nell’ultima riga è presente una nota che precisa che la CPU in stato di inattività non costituisce un vantaggio.
Memoria, CPU durante la digitazione e numero di processi delle quattro app, misurati sulla stessa macchina con lo stesso script. Nell’ultima riga è presente una nota che precisa che la CPU in stato di inattività non costituisce un vantaggio.

Gli editor Markdown vengono spesso presentati così.

Veloce. Leggero. Fluido.

Ma se dai numeri vengono escluse le condizioni, non sono diversi dagli aggettivi. Quando è stata misurata la CPU in stato di inattività e per quanto tempo. Da quale punto a quale punto è stato calcolato il tempo di avvio. Perché non è possibile confrontare numeri ottenuti in condizioni diverse.

Per questo abbiamo stabilito otto indicatori di prestazione che mote rende pubblici. Per ciascun indicatore abbiamo documentato il metodo e le condizioni di misurazione, gli elementi esclusi, le regole di confronto, le precauzioni e il budget. Abbiamo inoltre collegato uno per uno gli script di misurazione.

I documenti, i risultati e il codice usano tutti gli stessi nomi. Così è possibile risalire immediatamente all’origine di ogni numero.

I numeri devono essere accompagnati dalle condizioni

mote rispetta quattro principi.

Per ogni misurazione salviamo insieme il valore e l’unità, la statistica, il numero di campioni e i campioni grezzi. I risultati privi di unità vengono rifiutati durante la fase di verifica.

Non riportiamo valori che non abbiamo misurato. Se un valore non può essere misurato, lo lasciamo vuoto indicandone il motivo. Non lo riempiamo con una stima.

Effettuiamo i confronti soltanto sulla stessa macchina e nella stessa sessione. Non affianchiamo numeri ottenuti in giorni diversi o su dispositivi diversi.

Pubblichiamo insieme ai numeri anche le condizioni di misurazione. In particolare, indichiamo sempre la frequenza di aggiornamento e il governor della CPU. Se queste condizioni sono diverse, non è possibile confrontare correttamente la latenza e il tempo di avvio.

Una riga di output prodotta eseguendo una volta il gate — exec→finestra 246 ms, primo frame 275 ms, frame in stato di inattività 0, CPU in stato di inattività 0,10 %, PSS 121 MB, thread 12. La riga grigia sottostante è lo spazio in cui vengono annotate le condizioni che hanno prodotto questi numeri
Una riga di output prodotta eseguendo una volta il gate — exec→finestra 246 ms, primo frame 275 ms, frame in stato di inattività 0, CPU in stato di inattività 0,10 %, PSS 121 MB, thread 12. La riga grigia sottostante è lo spazio in cui vengono annotate le condizioni che hanno prodotto questi numeri

Non abbiamo inventato nuovi metodi di misurazione.

Per misurare la latenza dalla pressione di un tasto al cambiamento sullo schermo utilizziamo esattamente il metodo impiegato da Typometer di Pavel Fatin. Il tasto viene premuto dall’esterno dell’app e si controlla quanto tempo passa prima che cambi un pixel. Abbiamo suddiviso il tempo di avvio in fasi, come fa VS Code, distinguendo tra avvio a freddo e avvio a caldo.

Il principio secondo cui la latenza deve essere misurata da un’estremità all’altra, e non all’interno del framework, viene da un articolo di Dan Luu.

Abbiamo effettuato direttamente il confronto nelle stesse condizioni

Per le prestazioni delle app concorrenti non abbiamo citato numeri provenienti da altre fonti. Le abbiamo misurate direttamente sullo stesso portatile.

Abbiamo aperto lo stesso documento da 100 KB ed eseguito ogni app sette volte con lo stesso script. Per tutte abbiamo utilizzato la schermata di modifica inline e impostato il puntatore nella stessa posizione.

L’utilizzo complessivo della memoria da parte dei processi era il seguente.

  • mote: 78 MB
  • Typora: 453 MB
  • Obsidian: 361 MB
  • MarkText: 416 MB

Durante la digitazione, l’utilizzo della CPU su un singolo core era rispettivamente del 10,9%, 103%, 152% e 136%. Il numero di processi era rispettivamente 1, 8, 7 e 6.

L’utilizzo della memoria di mote era da 4,6 a 5,8 volte inferiore. La CPU utilizzata durante la digitazione era da 9,4 a 14 volte inferiore.

Abbiamo calcolato la memoria usando il PSS anziché l’RSS. L’RSS può contare più volte la memoria condivisa da diversi processi. Il PSS suddivide la memoria condivisa in base al numero di processi. È anche lo stesso metodo usato dal monitor di sistema.

Abbiamo lasciato invariati anche i numeri sfavorevoli

Quando le app erano semplicemente aperte, l’utilizzo della CPU era dello 0,0% per mote, dello 0,1% per Typora, dello 0,8% per Obsidian e dello 0,6% per MarkText.

Anche Typora non utilizzava quasi per nulla la CPU in stato di inattività. Pertanto non possiamo presentare il fatto che «quando rimane aperto non fa nulla» come un vantaggio rispetto a Typora.

La shell web utilizzava il 3,6%, risultando anzi peggiore di Typora.

Eliminare i timer ripetitivi interni all’app rimane importante. Ma i principi da rispettare e i vantaggi competitivi sono due questioni diverse.

Non abbiamo confrontato i frame in stato di inattività con quelli delle app concorrenti. L’obiettivo di mote è 0 frame nell’arco di 10 secondi, ma le altre app non dispongono di un contatore di frame che possa essere verificato nello stesso modo.

Per questo abbiamo lasciato vuote le caselle delle app concorrenti. Una casella vuota non equivale a zero.

Se non è possibile confrontare, non confrontiamo

Verifichiamo inoltre se il file originale rimane invariato quando viene aperto e salvato senza apportare modifiche.

mote verifica 652 esempi CommonMark. Inoltre apre e salva nuovamente tutti i documenti del repository, controllando che siano identici byte per byte. Se anche uno solo risulta diverso, lo consideriamo un bug di perdita dei dati, non un problema di prestazioni.

Non abbiamo riportato i risultati delle app concorrenti. Questo perché era difficile automatizzare il processo di salvataggio nelle stesse condizioni.

Prima della misurazione controlliamo anche lo stato della macchina. Se è in corso una compilazione, non avviamo la misurazione. Blocchiamo il browser soltanto quando sta effettivamente utilizzando molta CPU. Il carico medio, la percentuale di CPU inattiva, i criteri decisionali e i valori rilevati al momento della misurazione vengono tutti registrati nei risultati.

Questa regola è nata dopo un insuccesso.

Avevamo misurato il tempo di avvio lasciando aperto un browser che utilizzava molta CPU, e sembrava che le prestazioni fossero peggiorate. Alternando le misurazioni del commit precedente e di quello corrente con lo stesso carico, abbiamo scoperto che la causa non era una regressione del codice, bensì il carico della macchina.

Da allora non valutiamo più il tempo di avvio sulla base di un unico valore assoluto.

Se si supera il budget, non è possibile effettuare il merge

Il budget delle prestazioni non è soltanto un obiettivo scritto nella documentazione. È un criterio che deve essere rispettato affinché la build venga approvata.

I criteri sono suddivisi in hard e report.

hard comprende gli elementi i cui valori sono stati stabiliti in un documento decisionale. Se anche uno solo supera il limite, la verifica fallisce. Non è prevista nemmeno un’approvazione separata per le eccezioni.

report comprende gli elementi per i quali non esistono ancora prove sufficienti o che sono fortemente influenzati dai limiti della piattaforma. Il valore viene registrato, ma non blocca la build.

Se si blocca la build sulla base di numeri non sufficientemente comprovati, le persone finiscono per evitare la misurazione stessa. Per questo utilizziamo come gate soltanto criteri certi.

Sei righe di criteri hard nella tabella del budget — frame in stato di inattività 0 / 10 s, CPU in stato di inattività 0,3 %, tasto→pixel p95 misurato dall’esterno 33,4 ms, elaborazione interna del tasto p95 4 ms, quota di nostra competenza nell’avvio a freddo 10 ms, quota di nostra competenza nella memoria 8 MB. La colonna di destra è lo spazio in cui viene indicato il metodo di misurazione di ciascun indicatore
Sei righe di criteri hard nella tabella del budget — frame in stato di inattività 0 / 10 s, CPU in stato di inattività 0,3 %, tasto→pixel p95 misurato dall’esterno 33,4 ms, elaborazione interna del tasto p95 4 ms, quota di nostra competenza nell’avvio a freddo 10 ms, quota di nostra competenza nella memoria 8 MB. La colonna di destra è lo spazio in cui viene indicato il metodo di misurazione di ciascun indicatore

Gli script di misurazione, i CSV originali e i risultati JSON vengono conservati insieme nel repository. Eseguendo lo stesso script nelle stesse condizioni è possibile ricreare la tabella. Stiamo inoltre preparando la pubblicazione degli strumenti di misurazione e dei documenti di prova in un repository pubblico di benchmark.

Scegliere soltanto i numeri favorevoli non significa rendere pubblici i dati.

Mostrare insieme che cosa è stato misurato e come, quali erano le condizioni e che cosa non è stato possibile misurare. È così che mote rende pubblici i propri numeri.

← Meno recentiCome abbiamo fatto in modo che non consumi CPU quando resta semplicemente apertoPiù recenti →Abbiamo scelto il file come fonte di verità, così da salvare solo i byte digitati dall’utente
Segui gli aggiornamenti via RSS.
Lascia solo la scrittura.
Italiano
© 2026 mote