(轉)netty、mina性能對比分析


轉自:

http://blog.csdn.net/mindfloating/article/details/8622930

流行 NIO Framework netty 和 mina 性能測評與分析

測試方法
采用 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 框架程序性能表現的關鍵因素。
 
下面分別分析下 mina 和 netty buffer 的動態分配實現
mina
     buffer 分配方式:
     默認實現采用了 HeapByteBuffer,每次都是直接調用  ByteBuffer.allocate(capacity) 直接分配
     
     buffer 分配大小預測:
     根據每次讀事件實際讀到的字節數計算分配 buffer 的大小,若實際讀到字節將 ByteBuffer 裝滿,說明來自網絡的數據量可能較大而分配 buffer 容量不足,則擴大 buffer 一倍。
     若連續 2 次讀到的實際字節數小於 buffer 容量的一半,則縮小 buffer 為原來的一半
 
netty
     buffer 分配方式
     默認實現采用了 DirectByteBuffer,並且實現了 buffer cache,只要 buffer 大小不改變會重復利用已經分配的 buffer
     
     buffer 分配大小預測:
     初始化了一張 buffer size 靜態分配表如下(截取部分),假如當前默認 buffer 為 2048
     [1024, 1152, 1280, 1408, 1536, 1664, 1792, 1920, 2048, 2304, 2560, 2816, 3072, 3328, 3584, 3840, 4096]
                                           |      |    |                       |
                                           A      D    B                       C
        
     根據每次讀事件實際讀到的字節數,進行預測下一次應該分配的 buffer 大小。
     若實際讀到的字節數大於等於當前 buffer(上圖 B 位置) 則將當前 buffer 增大到上圖示 C 位置,每次增大步進為 4
     若連續 2 次實際讀到的字節數小於等於 A 位置指示的 buffer 大小,則縮小 buffer 到 D 位置
     
從上面的對比分析可以看出,mina 采用了相對簡單的 buffer 分配和預測方式,buffer 的增長和縮小比例相同。
而 netty 采用了一種相對復雜點的 buffer 分配方式,buffer increment faster decrement slower。
事實證明 netty 的分配方式更有效的避免的 buffer 分配中的抖動問題(忽大忽小),而 buffer 分配抖動正是影響 io 吞吐的罪魁禍首。
mina 測試中 5k 報文正好產生了 buffer 分配抖動導致 io 吞吐大受影響,通過修改 mina 源碼采用固定 buffer 大小來測試則有效避免了 buffer 抖動,io 吞吐也恢復正常。
但實際情況下,固定 buffer 肯定不是有效的方式,不能很好的適應各種網絡環境的復雜性,但采用動態 buffer 分配時算法需首要考慮避免抖動。
 
另外可以看出 netty 的 cpu 消耗明顯高出 mina 不少,懷疑 netty 采用的 executor 實現(OrderedMemoryAwareThreadPoolExecutor)存在比較多的鎖競爭和線程上下文切換。
下面是一組不使用 executor 時 netyy 的測試數據,其他指標都差不多但 cpu 明顯下降不少
netty cpu
1k 75%
2k 125%
5k 126%
10k 126%
50k 118%
100k 116%
 
 
測試總結

mina:   需進一步優化其 buffer 分配,避免分配抖動導致的 io 吞吐波動
netty: 需進一步優化默認 executor 的實現,降低 cpu 消耗
 
其實 netty2 和 mina 都出自同一人 Trustin Lee,后來他轉投 apache 項目組將 netty 交給了社區繼續維護,之后重新設計 mina 這個框架。
從使用者感受上來說 mina 的 api 接口設計明顯比 netty 更優雅。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM