Imported from yaiiow159/flow-sentinel (
.claude/skills/bench/SKILL.md). Install upstream withnpx skills add yaiiow159/flow-sentinel --skill bench. Copyright stays with the author.
對照壓測(平台執行緒 vs 虛擬執行緒)
為什麼需要這個
README 上的效能數字若沒有可重現的產生方式,就只是宣稱。被追問「什麼環境、怎麼量的」 而答不出來,比沒有數字更糟。這個 skill 把量測條件固定下來,並把環境資訊一起寫進報告。
使用前提
mvn clean install已完成(需要 demo 的可執行 jar)- Redis 已啟動(
node .claude/skills/dev-stack/up.js) - 連接埠 8080 未被占用
執行方式
node .claude/skills/bench/bench.js
參數:--duration=20(量測秒數)、--warmup=15、--concurrency=200、
--path=/api/v1/report、--port=8080。
報告會寫到 docs/benchmark/<時間戳>.md。不要手動編輯那些檔案——
數字的價值來自可重現性,要更新就重跑。
三個一定要保留的機制
這三件事都是實作時踩過坑才加上的,改動腳本時請不要拿掉:
- 每組量測前後強制清掉殘留的 JVM。
child.kill()在 Windows 上不保證讓 JVM 消失; 殘留的話下一組會因 8080 被占用而直接退出,負載打到的還是上一組的應用—— 兩組量出幾乎一樣的數字,看起來像「兩種模型沒差別」,實際上是拿同一個應用跟自己比。 啟動後也會檢查子程序還活著,沒活著就直接報錯而不是回報假數據。 - 壓測端要多程序。 單一 Node 程序約 2,100 QPS 就到頂(實測單程序 1,416 vs 5 程序 5,483), 量到的會是壓測端自己的天花板。
- 請求要有逾時。 少了它,只要一條連線卡住,整個壓測會無限期停住(實測踩過)。
靈敏度自我驗證
量不出差異時,要能區分「真的沒差別」與「工具看不見差別」。
用 --platform-threads=50 把對照組的執行緒池縮小,理論上平台組會卡在
50 ÷ 50ms = 1,000 QPS,虛擬執行緒則不受此限:
node .claude/skills/bench/bench.js --concurrency=600 --rounds=1 --platform-threads=50
實測 771 QPS vs 4,074 QPS(平台執行緒 68 條 vs 41 條),與理論相符—— 工具確實看得見差異。改過壓測邏輯後建議重跑這一項確認沒有失去靈敏度。
輪數與可信度
--rounds 預設 3。release-check --full 為了控制時間只跑 2 輪,那是煙霧測試等級——
足以發現「效能整個掉下來」,但不足以支撐對外引用的數字。
實測同樣條件下,3 輪得到 +103%、2 輪得到 +42%,單輪 QPS 甚至在 2,076~5,984 之間跳動。
要寫進文件或簡報的數字,至少跑 5 輪並附上各輪範圍。
量測方法上的取捨
- 兩組在同一次執行中依序量測,同機、同暖機時間。分兩次跑的數字不能互相比較。
- 暖機 15 秒後丟棄:JIT 尚未編譯熱路徑時的數字會嚴重偏差,而且會系統性地讓先跑的那組吃虧。
- 記憶體看 RSS 不看 heap:虛擬執行緒省下的是 OS 執行緒堆疊,那不在 JVM heap 裡,
只看 heap 會誤以為兩者沒差別。腳本在 Windows 用
tasklist、Linux 讀/proc/<pid>/status。 - 預設打
/api/v1/report:那個端點以 sleep 模擬下游 I/O 等待。 改打立刻回應的端點(如/api/v1/orders)量到的只是框架與限流本身的開銷, 虛擬執行緒在那種情境本來就沒有優勢,兩組會很接近——那不是 bug。 - 壓測端與被壓端同機:負載產生器本身會吃 CPU,絕對值會低於分離部署, 但兩組條件相同,相對差異仍可比較。報告裡也寫了這一點。
判讀結果
- 虛擬執行緒沒有明顯提升:先確認測的端點會不會阻塞(見上一節),
再跑
loom-audit --runtime確認沒有 carrier thread 被 pin 住。 - 平台執行緒數:
jvm.threads.live只算平台執行緒,虛擬執行緒不在內。 報告分「閒置」與「負載峰值」兩欄:閒置時差距很明顯(平台 200+、虛擬約 30), 但負載期間虛擬執行緒那組也會長到相近的數字——那是 ForkJoinPool 的補償執行緒 (carrier 被阻塞時排程器會補新的),屬預期行為,不代表虛擬執行緒沒生效。 這一欄容易誤讀,判斷效益請以 QPS 與延遲為準。 - 429 出現在回應狀態裡:表示限流有作用,該端點的閥值對這個併發量來說太低, 量到的會是攔截路徑的效能。要量執行緒模型請用預設端點。
之後若要換成 JMeter
目前用內建的 benchmark/load.js(Node,無外部相依),因為本機沒有 JMeter,
而讓 skill 依賴一個沒安裝的東西等於不能用。方法論(同一次執行、暖機、RSS、環境資訊)
才是這個 skill 的價值,換成 JMeter 只需替換負載產生的那一段。