Java Web Application Efficient Test
Java Web Application Efficient Test
1. 臨時找效能問題:JFR
若只是想知道 PDF 轉換時間花在哪裡,使用 Java Flight Recorder,不必修改 PdfReport:
1
2
3
java \
-XX:StartFlightRecording=duration=60s,filename=phychkmgr.jfr,settings=profile \
-jar application.jar
WAR 部署時則把參數加到應用程式伺服器的 JVM 啟動參數。
JFR 能看到方法耗時、CPU、記憶體配置與 GC,比單一開始/結束時間更有診斷價值。Oracle 官方也支援 JVM 啟動時直接開始錄製。1
2. 長期觀察每次 PDF 匯出:正式日誌或 Timer
若想知道實際使用者每次匯出花多久,可以把計時寫成正式 DEBUG 日誌,而不是註解:
1
2
3
4
5
6
7
8
9
10
long startedAt = System.nanoTime();
try {
return createPdf();
} finally {
long elapsedMillis = TimeUnit.NANOSECONDS.toMillis(
System.nanoTime() - startedAt
);
logger.debug("PDF report generated in {} ms", elapsedMillis);
}
計算經過時間應使用 System.nanoTime();Oracle 明確說明它是用來測量經過時間,currentTimeMillis() 則是系統時間。2
使用 logger.debug() 後,可以由日誌設定控制是否輸出,不必反覆修改原始碼。SLF4J 的參數式日誌也能避免不必要的字串組合。3
若系統本來已有 Prometheus、Micrometer 或其他監測平台,應使用 Timer 記錄次數、總時間、最大值與百分位數,不應只印一行日誌。4
3. 要比較 iText 與 OpenPDF 效能:JMH
這不是一般單元測試。應建立獨立 JMH benchmark:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@State(Scope.Benchmark)
public class PdfReportBenchmark {
private byte[] pc1010Docx;
@Setup
public void setUp() throws IOException {
pc1010Docx = Files.readAllBytes(Path.of("PC1010-merged.docx"));
}
@Benchmark
public byte[] convertPc1010() {
ByteArrayOutputStream result = new PdfReport().createReport(
new ByteArrayInputStream(pc1010Docx)
);
return result.toByteArray();
}
}
JMH 會處理 JVM 暖機、多次量測及不同 fork。OpenJDK 將 JMH 定位為 JVM 的微型、毫秒級及大型 benchmark 工具。5
This post is licensed under CC BY 4.0 by the author.