第3章:核心之下,唯有 Syscall 與熱血
「你打算怎麼做?」Gosling 將一杯咖啡放到我桌上,聲音低沉卻透著期待。
我望著 Solaris 2.5.1 的調度器原始碼,思考良久,終於開口:「我們得讓 JVM 在這台機器上跑起來,就像是在自己的領地上奔跑一樣。那代表──Solaris 必須為 Java 而重生。」
我用紅筆圈出了一個函數:
void ts_dispatch() {
...
}
「這就是問題的核心。Solaris 的 TS(time-sharing)類別太保守了。它的調度策略優先考慮系統整體公平性,對於像 JVM 這種內部擁有大量短命工作執行緒的系統來說,反而是一種拖累。」
「JVM 的 GC 執行緒、編譯執行緒、甚至是 class loader,全都需要更快速的切入點。」我站起來,指著白板上的一張 JVM 執行緒圖譜。
【JVM 執行緒與作業系統的連動圖】
[ Java Thread ] -> [ JVM Thread Object ]
↓
[ OS-level LWP (via libthread) ]
↓
[ Kernel Thread (Solaris TS class) ]
↓
--> CPU Scheduler
「現在,我們需要把 JVM 的核心執行緒標記出來,讓 Solaris 認得這些 thread 是高優先等級的 native application worker。這樣在調度時就能獲得特別照顧。」
Gosling 微微點頭:「你打算怎麼實現?Solaris 調度器不是很輕易就能插入外部策略的。」
「那我們就不插入──我們直接寫死進去。」
我快速打開一個 patch file,開始加入識別 JVM thread 的 kernel-level tag:
#define THREAD_IS_JVM(t) ((t)->proc->p_argv && strstr((t)->proc->p_argv[0], "java"))
void ts_update_priority(kthread_t *t) {
if (THREAD_IS_JVM(t)) {
t->pri = maxclsyspri - 1; // JVM threads just below system daemons
t->ts_flags |= TS_KENNY_PATCH;
}
}
「這是作弊嗎?也許。但這樣 GC thread 就不會因為過度公平被推遲了十幾個 context switch cycle。」
我一邊敲鍵盤,一邊熱血地說道:
「為了讓 Java 世界裡的 System.gc() 不再成為性能殺手,我們願意將公平拋諸腦後!」
【HotSpot JVM 內部】
「如果你打算調教 Solaris,那我來負責 JVM。」Gosling 說。
他拿出一個未曾公開的 HotSpot 原型分支──sun/internal/hotspot/vm8,這是尚未完成的 JIT 優化模組。
「這是我試著將 inlining decision 與作業系統 thread priority 結合的一部分。如果我們知道哪些方法會被 scheduler 提早執行,就可以針對這些方法做 aggressive inlining。」
他開啟一段 Java class:
@SolarisAffinity(level = Priority.CRITICAL)
public class GCWorker implements Runnable {
@Override
public void run() {
// critical young gen sweep
}
}
「我們在 JVM 中加了一個 Solaris-aware annotation processor,會在 JIT 編譯時根據這個註解為 native thread 設定調度優先順序。」
我愣了一下。
「所以你是說……我們現在的 JIT 編譯器,能根據 Java annotation 對 kernel 調度進行最佳化?」
「正是如此。」Gosling 笑了。
「JVM 不再只是 bytecode 的執行機器──它是一個和作業系統互動的智能 runtime 生物體。你喚醒 Solaris 的內核,我喚醒 JVM 的靈魂。現在,我們讓它們連結起來。」
【測試結果】
Gosling 將修正後的 HotSpot prototype 編譯完成,我將新調度核心編譯進 Solaris 核心映像,我們同時輸入最後一行啟動指令:
$ ./start-java -Xserver -XX:+UseHotSpotSoulGC
螢幕閃動。
[INFO] Kenny Solaris-Kernel Patch: Active
[INFO] JVM initialized in 1.29s
[INFO] GC Throughput: +183%
[INFO] Stop-the-world pause: 17ms (was 105ms)
我愣住了,接著緩緩握緊拳頭。
「這是……我見過最完美的 JVM 啟動過程。」
Gosling 拿起筆電,將剛才的實驗結果寫入一封信裡:
給未來的工程師們:
我們曾夢想過一個平台獨立的世界,但我們更相信──當系統與語言合而為一,那就是真正的進化。
太陽不會落下,只要 JVM 還在燃燒。
——James Gosling & Peter Chan