NIO系列6:流行 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 更优雅。

转载于:https://my.oschina.net/vdroid/blog/225165

NIO系列六:流行 NIO Framework netty 和 mina 性能测评与分析相关推荐

  1. (一:NIO系列)JAVA NIO 简介

    出处:JAVA NIO 简介 Java 中 New I/O类库 是由 Java 1.4 引进的异步 IO.由于之前老的I/O类库是阻塞I/O,New I/O类库的目标就是要让Java支持非阻塞I/O, ...

  2. 踏莎行·术 - NIO系列1:框架拆解

    最近一年用NIO写了不少网络程序,也研究了一些开源NIO网络框架netty.mina等,总结了一下NIO的架构特点. 无论是netty还是mina它们都在java原生NIO的基础上进行了完善的封装,虽 ...

  3. java nio netty 教程,4. 彤哥说netty系列之Java NIO实现群聊(自己跟自己聊上瘾了),netty实现...

    4. 彤哥说netty系列之Java NIO实现群聊(自己跟自己聊上瘾了),netty实现 你好,我是彤哥,本篇是netty系列的第四篇. 欢迎来我的公从号彤哥读源码系统地学习源码&架构的知识 ...

  4. epoll nio区别_大厂面试系列(二)::NIO和Netty

    NIO和Netty面试题 NIO 阐述 NIO原理? BIO/NIO/AIO有什么区别?有那些实现? 讲讲NIO的原理与实现?NIO用到了哪个经典技术思想?JDK1.8中NIO有做什么优化 了解多路复 ...

  5. java nio多路复用_Java NIO系列教程(六) 多路复用器Selector

    多路复用器Selector是Java NIO编程的基础,熟练地掌握Selector对于掌握NIO编程至关重要.多路复用器提供选择已经就绪的任务的能力.简单来讲,Selector会不断地轮询注册在其上的 ...

  6. Netty和JDK源码来看Netty的NIO和JDK的NIO有什么不同

    JDK底层提供了NIO实现,在Linux环境会调用内核epoll. 但是Netty通过JNI的方式提供了Native Socket Transport,为什么Netty要自己搞一套NIO呢? 这篇文章 ...

  7. Java NIO系列教程(十二) Java NIO与IO

    原文地址:http://tutorials.jenkov.com/java-nio/nio-vs-io.html 作者:Jakob Jenkov   译者:郭蕾    校对:方腾飞 当学习了Java ...

  8. Java NIO系列教程(三) Buffer

    2019独角兽企业重金招聘Python工程师标准>>> Java NIO中的Buffer用于和NIO通道进行交互.如你所知,数据是从通道读入缓冲区,从缓冲区写入到通道中的. 缓冲区本 ...

  9. Java NIO系列教程(五) 通道之间的数据传输

    在Java NIO中,如果两个通道中有一个是FileChannel,那你可以直接将数据从一个channel(译者注:channel中文常译作通道)传输到另外一个channel. transferFro ...

  10. Java NIO系列教程(四) Scatter/Gather

    转载自   Java NIO系列教程(四) Scatter/Gather 译文地址  作者:Jakob Jenkov   译者:郭蕾 Java NIO开始支持scatter/gather,scatte ...

最新文章

  1. javascript知识点
  2. WebsiteSpark是免费软件吗?
  3. 剪切粘贴时总是上次的内容_Quicker 1.4版本更新内容
  4. php如何和c进行数据交换,PHP与 后台c交换数据 | 学步园
  5. python 示例_Python TextCalendar类别| pryear()方法与示例
  6. 在linux环境获取pcie卡信息,如何Linux下得到CPU、内存及PCI信息
  7. 《深度学习Python实践》第18章——持久化加载模型
  8. 拓端tecdat|R语言广义相加(加性)模型(GAMs)与光滑函数可视化
  9. 【C++】atomic简介
  10. 2021年中国计算机视觉产业及其重点企业分析(商汤科技VS旷视科技VS依图科技VS云从科技)[图]
  11. MySQL系列之STRAIGHT JOIN用法简介
  12. CVPR2014 tracking
  13. vue3获取url后面参数
  14. 数据流程分析【停车场管理系统】
  15. 调皮捣蛋的孩子--十大负面测试用例
  16. Zookeeper客户端Curator Framework使用
  17. Flowable UI制作流程图
  18. 最详尽的4K技术科普
  19. IEEE会议期刊检索查找
  20. trim函数 php,php删掉空格trim函数不起作用问题解决方法

热门文章

  1. 无人机图像的目标检测的学习
  2. mysql存储emoji表情
  3. java怎样定义和使用数组,Java一维数组的定义和使用
  4. HDFS分布式文件系统知识总结
  5. Android仿IOS有弹性ScrollView
  6. 微信和QQ,终于可以互通了
  7. where 1=1 是什么鬼?SQL中有这玩意?
  8. 通过GPUImage实现40+种滤镜与实时美颜功能
  9. oracle fileperset,RMAN具体使用方法
  10. matlab 输入矩形序列,从python调用Matlab函数:“初始值设定项必须是矩形嵌套序列”...