WSL2 開發容器與 9P 協議性能測試
tags: WSL2, Dev Container
category: Performance
description: WSL2 開發容器與 9P 協議性能測試
created_at: 2026/09/10 12:00:00

前言
先前在開發 Side Project 時,因為現今大多透過 AI 來協助開發,很容易不知不覺就產生了很多的程式碼以及測試程式(即使經過你的規劃,都在你的預期中),因此效能的問題也相較於以往更容易浮現。
只是在以前開發時通常是人工撰寫程式碼,即使有那麼一點的效能問題,也不會造成太大的困擾;而現今因為 AI 撰寫的速度非常快,很容易在短時間內產生大量程式碼,進而暴露出更多的效能瓶頸。
而在先前我開發的習慣就是讓程式碼可以隨處帶著跑,所以我都會在 Dev Container 中進行開發,這樣不論是在本地還是其他環境,都能保持一致的開發體驗。
然而我又是個很不喜歡汙染宿主環境的人,因此 Dev Container 對我來說是非常理想的選擇,我連 ,而是完全依賴 Docker Desktop 都不會在宿主環境中安裝WSL2 來安裝 Docker。
事前準備
無,但如果你想測,可以先準備好 WSL2 與 Docker 環境,並確保 Dev Container 已正確配置。
以前怎麼做
- 打開桌面(或其他
Windows檔案系統)的資料夾,然後建立一個新的專案資料夾。 - 用
VS Code打開該資料夾,(假定已經安裝好Dev Container擴充功能)。 Reopen in Container,將專案資料夾以Dev Container的方式打開。- 開始在
Dev Container中進行開發,所有的程式碼與依賴都會在容器內運行,而不會影響宿主環境。
這感覺是平常到不行的開發方式,但在效能上可能會有一些限制,特別是當專案變得越來越大時。
問題所在
在上述的開發方式中,所有的程式碼都存放在 Windows 的檔案系統中,然後透過 9P 協議掛載到 Dev Container 中。
而 Dev Container 實際上是跑在 WSL2 的虛擬化環境中,透過 9P 協議與宿主的 Windows 檔案系統進行交互。
這就意味著每次 Dev Container 需要讀寫程式碼時,都必須透過 9P 協議與宿主的 Windows 檔案系統進行通訊,這會帶來額外的延遲,特別是在大量小檔案操作時,效能瓶頸會更加明顯。
換句話說,當專案規模變大,檔案數量增加時,這種開發方式的效能問題會變得更加突出,可能會影響開發體驗。
這讓我想到很久以前開發時所錄製的影片,當 WSL 碰到稍微大一點的 Codebase
只是當時沒有意識到是因為 WSL2 與 Windows 檔案系統之間的 9P 協議造成的性能瓶頸。
而今天剛好有空就來測試一下這個效能瓶頸,看看在不同的開發環境下,WSL2 與 9P 協議的影響到底有多大。
不過畢竟這種測試在各種不同機器上執行,結果可能會有所差異,因此僅供參考,只是大概了解效能瓶頸的情況就好。
測試設計
我請 AI 針對幾種常見的讀寫刪除檔案等操作設計了測試,並在不同的環境下進行了性能測試,最終得到以下結果。

其中 9P 指的就是 WSL2 與 Windows 檔案系統之間的通訊協議,而 EXT4 則是 WSL2 虛擬化環境內的原生檔案系統。
從圖中可以看出,9P 的性能明顯低於 EXT4,特別是在大量小檔案操作時,差距更加明顯。

這張圖展示了 9P 與 EXT4 的性能比率,可以更直觀地看到兩者之間的差距,在大檔案操作時,差距相對較小,但在大量小檔案操作時,9P 的性能劣勢依然明顯。
既然知道了這兩者之間的性能差距,那我們來看一個實際的例子,展示在開發過程中,9P 與 EXT4 的性能差異對開發體驗的影響。
實際開發中的性能差異
在這個測試中,我們準備了一份 package.json,長得像是下面這樣:
{
"name": "fs-install-case",
"private": true,
"version": "0.0.0",
"description": "實際案例:在 9p 與 ext4 上安裝同一棵依賴樹,把機制層的 per-op 數字接回真實的等待時間。刻意選純 JS 套件(無 node-gyp 編譯),讓時間差來自檔案操作而非 CPU。",
"scripts": {
"bench:ci": "npm ci --offline --ignore-scripts --no-audit --no-fund --legacy-peer-deps",
"bench:prime": "npm install --package-lock-only --legacy-peer-deps && npm ci --ignore-scripts --no-audit --no-fund --legacy-peer-deps && rm -rf node_modules",
"count": "printf 'files=%s dirs=%s\\n' \"$(find node_modules -type f | wc -l)\" \"$(find node_modules -type d | wc -l)\"",
"bytes": "du -sh node_modules"
},
"devDependencies": {
"@playwright/test": "^1",
"@sveltejs/adapter-node": "^5",
"@sveltejs/kit": "^2",
"@types/node": "^22",
"@typescript-eslint/eslint-plugin": "^8",
"@typescript-eslint/parser": "^8",
"@vitest/coverage-v8": "^2",
"autoprefixer": "^10",
"eslint": "^9",
"eslint-plugin-svelte": "^2",
"postcss": "^8",
"prettier": "^3",
"prettier-plugin-svelte": "^3",
"svelte": "^5",
"svelte-check": "^4",
"tailwindcss": "^3",
"typescript": "^5",
"vite": "^6",
"vitest": "^2"
}
}
接著你可以透過一個 dev container 同時掛進 windows 與 wsl2 原生的檔案系統,然後在兩個環境中分別執行相同的安裝操作,觀察性能差異。
然後為了避免網路因素影響測試結果,我們先在 container 中將所有依賴下載到本地緩存,這樣在後續的安裝過程中就不需要再從網路下載依賴,從而保證測試結果的穩定性。
最終我們得到了以下的性能測試結果:
數字是我手動測試來的,只是圖是AI繪製的,所以可以對數字有信心
可以看到在 9p 掛載的檔案系統中,安裝依賴以及刪除 node_modules 的速度明顯慢於在 EXT4 原生檔案系統中,這也印證了前面測試中 9P 與 EXT4 的性能差距。
所以.. 原生檔案系統在哪
進入 wsl 的時候,我們會發現預設的目錄就是當前目錄,只是前面多了 /mnt/ 開頭,這就是 WSL2 對 Windows 檔案系統的掛載位置。換句話說,/mnt/c/Users/ 對應的就是 C:\Users\,這部分就是通過 9P 協議來進行讀寫的。
而 WSL2 的原生檔案系統則位於 / 根目錄下,通常是 ext4 格式的虛擬磁碟。這部分的讀寫操作不需要經過 9P 協議,因此性能要比掛載的 Windows 檔案系統高得多。
換句話說,如果希望在 WSL2 中獲得更好的檔案操作性能,應該盡量將專案放在 WSL2 的原生檔案系統中,而不是掛載的 Windows 檔案系統中。
因此,在使用 WSL2 進行開發時,將專案放在原生的 ext4 檔案系統中,可以顯著提升檔案操作的性能,從而改善開發體驗。
當然也可以透過 VM 然後 SSH 進入虛擬機中的原生檔案系統來進行開發,這樣同樣可以獲得接近原生的檔案操作性能。
懶人包
$ wsl
$ cd ~
$ mkdir my-project
$ code my-project
然後後面就都一樣了。
檢查
可以透過以下命令來檢查是否正確的使用到 WSL2 的原生檔案系統。
$ grep $(pwd) /proc/mounts
如果輸出中顯示的掛載點是 / 開頭的路徑,則說明專案位於 WSL2 的原生檔案系統中;如果是 /mnt/ 開頭的路徑,則說明專案位於掛載的 Windows 檔案系統中。
也可以看掛載點後面的檔案系統類型,如果是 9p,則說明是掛載的 Windows 檔案系統;如果是 ext4,則說明是 WSL2 的原生檔案系統。
補充資料
結論
總結來說,9P 協議雖然方便了 WSL2 與 Windows 之間的檔案共享,也解決了跨系統檔案訪問的問題,但在性能上仍然存在明顯的劣勢。因此,對於需要頻繁進行檔案操作的開發場景,將專案放在 WSL2 的原生 ext4 檔案系統中,仍然是獲得最佳性能的選擇。