拖慢效能的不是 Markdown,而是網頁引擎
光是開著 Markdown 編輯器風扇就開始轉,並不是因為 Markdown 的成本很高。在相同條件下用同一份文件測量,就會發現成本來自渲染引擎和與時鐘綁定的迴圈。

我在筆記型電腦上開著 Markdown 編輯器。明明什麼都沒輸入,風扇卻開始轉了。
一開始我以為是 Markdown 造成的。以為是因為不斷重新繪製文件,所以才會這麼慢。
真的是這樣嗎?
我在相同條件下進行了比較
我把畫面大小、渲染方式和文件全部設成相同條件。開啟一份 7.5KB、113 行的文件後,持續 25 秒什麼都不做。輸入時,也用相同速度輸入相同文字。
使用網頁引擎繪製預覽的 apostrophe,閒置時 CPU 使用率為 34.6%,記憶體用量為 378MB。共有 5 個處理程序。
不使用網頁引擎、以行內方式繪製同一份文件的原型,CPU 使用率為 0.7%,記憶體用量為 64MB。只有一個處理程序。
兩者都在繪製 Markdown,但結果差異很大。
只關閉 apostrophe 的預覽後,CPU 使用率便降至 7.0%,記憶體用量也降至 133MB。應用程式和工具套件都沒有變。唯一改變的只是繪製預覽的方式。
我也測量了完全不繪製 Markdown 的文字編輯器。CPU 使用率為 2.2%,記憶體用量為 79MB。
繪製 Markdown 的原型反而更輕量。
這時才變得很明確。問題不在 Markdown。
即使什麼都不做,它每秒仍在運作 60 次
原因出在讓預覽捲動與本文保持同步的程式碼。
這段程式碼並不是只有在捲動時才執行。每隔 16ms,計時器就會喚醒,並在 WebKit 處理程序中執行 JavaScript。收到回應後,又會再次設定計時器。
即使沒有人碰視窗,它每秒仍會運作約 60 次。
使用網頁引擎後,編輯文件的區域和繪製預覽的區域就會變成兩個不同的世界。要讓兩邊的狀態保持一致,最簡單的方法就是持續確認。如果不另外測量閒置時的 CPU 使用率,這項成本很難被察覺。
輸入時的差異更大。apostrophe 的 CPU 使用率為 180%,原型則為 41%。
其中一邊每次按鍵時都要往返瀏覽器處理程序。另一邊只會重新為變更的行加上標籤。
我把測量結果變成了設計原則
原型並沒有採用什麼特別的最佳化。
樣式是透過文字上的標籤套用的。多次編輯會集中到一個執行後自行消失的一次性 idle 中。重新加上標籤的範圍僅限於發生變更的行。也只使用一個處理程序。
這不是增加了什麼,而是沒有放入不必要的東西。
之後,我訂下了兩項設計原則。
第一,不把網頁引擎納入相依套件。
第二,如果文件沒有變更,也沒有動畫,就不排定任何畫格、計時器或 tick。
這些原則很難在之後才補上。網頁引擎不是單純的函式庫,它會改變應用程式的結構。一旦加入,要移除它就等於要重新製作整個應用程式。如果沒有規則,計時器也會隨著每項功能各自增加一個。
但相對地,我也必須放棄簡單的做法。不能透過輪詢確認檔案變更,也不能把數學公式交給 WebView 處理。需要的版面配置必須自己製作。
為了不讓原則逐漸模糊,每次發布時都會在實際裝置上重新測量。

查看數據時也有需要注意的地方
實驗是使用軟體渲染進行的。CPU 使用率會比實際 GPU 環境更高。因此,應該看的是比例,而不是絕對值。
原型閒置時的 0.7% CPU 使用率,大多也是游標閃爍時產生的數值。關閉閃爍後,幾乎難以與 0 區分。
這並不表示所有以網頁引擎為基礎的應用程式都會遇到相同問題。這次的結果僅限於 apostrophe。也有像 Chromium 系列那樣,會在閒置狀態下減少工作的引擎。
原型的功能也不多。沒有表格、數學公式、匯出和搜尋功能。能夠比較的範圍只到渲染成本為止。
即使如此,有一點很明確。
產生成本的不是 Markdown,而是渲染引擎和不會停止的迴圈。
只要精確找出原因,輕量化就不再是一項新功能,而會變成一場減法。