測試方法 採用 mina 和 netty 各實現一個 基於 nio 的EchoServer,測試在不同大小網路報文下的效能表現
測試環境 用戶端-服務端: model name: Intel(R) Core(TM) i5-2320 CPU @ 3.00GHz cache size: 6144 KB cpu cores: 4 jdk: 1.6.0_30-b12 network: 1000Mb memory: -Xms256m -Xmx256m Linux: centos 5.7, kernel 2.6.18-274.el5
測試載入器: jmeter v2.4
版本: mina 2.0.7 netty 3.6.2.Final
配置: mina io-processor cpu 核心數 executor cpu 核心數 buffer 初始 buffer 大小,設定為 2048(2k) netty boss netty 預設配置 1 worker cpu 核心數 executor cpu 核心數 其實,從理論上來說, echo 型的應用不配置 executor 業務執行線程池會獲得更好的效能和更低的消耗,但考慮在真實業務應用中,真實的業務情境處理通常涉及各種複雜邏輯計算,緩衝、資料庫、外部介面訪問,為避免業務執行延時阻塞 io 線程執行導致吞吐降低,通常都會分離 io 處理線程 和 業務處理線程,因此我們的測試案例中也配置了業務執行線程池考查它們線程池的調度效能。
mina 線程池設定 io processor: IoAcceptor acceptor = new NioSocketAcceptor(Integer.parseInt(ioPool)); executor: acceptor.getFilterChain().addLast("threadPool", new ExecutorFilter(Integer.parseInt(executorPool))); netty 線程池設定 io worker: new NioWorkerPool(Executors.newCachedThreadPool(), Integer.parseInt(ioPool)) executor: new OrderedMemoryAwareThreadPoolExecutor(Integer.parseInt(executorPool), 0, 0)
測試結果
| mina |
tps |
cpu |
network io |
art(average response time)
|
90%rt(90% response time)
|
| 1k |
45024/sec
|
150%
|
50MB/sec
|
< 1ms
|
1ms
|
| 2k |
35548/sec
|
170% |
81MB/sec
|
< 1ms
|
1ms
|
| 5k |
10155/sec
|
90%
|
55MB/sec
|
3 ms
|
1ms
|
| 10k |
8740/sec
|
137% |
98MB/sec |
3ms |
4ms |
| 50k |
1873/sec |
128% |
100MB/sec |
16ms |
19ms |
| 100k |
949/sec |
128% |
100MB/sec |
33ms |
43ms |
| netty |
tps |
cpu |
network io |
art(average response time)
|
90%rt(90% response time)
|
| 1k |
44653/sec
|
155%
|
50MB/sec
|
< 1ms
|
1ms
|
| 2k |
35580/sec
|
175% |
81MB/sec
|
< 1ms
|
1ms
|
| 5k |
17971/sec
|
195%
|
98MB/sec
|
3 ms
|
1ms
|
| 10k |
8806/sec
|
195% |
98MB/sec |
3ms |
4ms |
| 50k |
1909/sec |
197% |
100MB/sec |
16ms |
18ms |
| 100k |
964/sec |
197% |
100MB/sec |
32ms |
45ms |
測試點評 mina 和 netty 在 1k、2k、10k、50k、100k 報文大小時 tps 接近 mina 在 5k 報文時有個明顯的異常(紅色標註),tps 較低,網路 io 吞吐較低,比較 netty 在 5k 報文的網路 io 吞吐 98MB/sec(基本接近前兆網卡極限) 5k 報文以上基本都能壓滿網路 io,瓶頸在 io,所以 tps 和 回應時間基本相差不大。
疑問,為什麼 mina 會在 5k 報文時 io 吞吐出現明顯降低。
測試分析
通過分析 mina 和 netty 的源碼,發現處理 io 讀事件時 buffer 分配策略上,兩個架構有一些區別。 在網路 io 處理上,程式每次調用 socket api 從 tcp buffer 讀取的位元組數是隨時變化的,它會受到報文大小,作業系統 tcp buffer 大小、tcp 協議演算法實現、網路鏈路頻寬各種因素影響。 因此 NIO 架構在處理每個讀事件時,也需要每次動態分配一個 buffer 來臨時存放讀到的位元組,buffer 分配的效能是影響網路 io 架構程式效能表現的關鍵因素。