测试方法
采用 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
根据每次读事件实际读到的字节数,进行预测下一次应该分配的 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 更优雅。
相关推荐
《NIO+Netty5视频教程与Netty源码剖析视频教程》是一份全面解析网络编程框架Netty的教育资源,旨在帮助学习者深入...通过结合视频教程和文本资料,学习者可以更系统地吸收和巩固Netty与NIO的知识,提升自己的专业技能。
Java异步NIO框架Netty实现高性能高并发无标题笔记 1. 背景 1.1. 惊人的性能数据 最近一个圈内朋友通过私信告诉我,通过使用Netty4 + Thrift压缩二进制编解码技术,他们实现了10W TPS(1K的复杂POJO对象)的跨 节点...
第4章,实现长连接客户端,以及采用多线程技术进行系统性能测试; 第5章,介绍Netty相关基础知识,并使用Netty实现长连接服务端的编码。 适用人群 具有一定的Java开发基础; 学习Java开发领域Spring框架之外的东西...
Netty是基于Java NIO构建的一个高性能、异步事件驱动的网络应用程序框架,它极大地简化了网络编程,特别是TCP和UDP套接字服务的开发。 Netty的特点: 1. **高度可定制化**:Netty允许开发者自定义各种协议编解码器...
Java NIO (Non-blocking Input/Output) 是Java平台中用于高效处理I/O操作的一种机制,它与传统的IO模型( Blocking I/O)相比,提供了更高级别的抽象,允许应用程序以非阻塞的方式读写数据,提高了并发性能。Netty是...
资源名称:Java_NIO框架Netty教程资源截图: 资源太大,传百度网盘了,链接在附件中,有需要的同学自取。
**NIO(非阻塞I/O)与Netty编程**是现代Java网络应用开发中的重要技术,它们在处理高并发、低延迟的网络通信场景中起着关键作用。本讲义详细介绍了这两种技术,旨在帮助开发者更好地理解和运用它们。 ### 一、BIO...
Netty和Mina的吞吐量和性能 نيز有所不同。在大量数据传输的情况下,Mina的吞吐量会出现明显的降低,而Netty保持稳定的吞吐量。Netty的buffer分配方式比Mina更复杂,能够更好地避免buffer分配中的抖动问题,从而...
netty开发之nio netty开发之nio netty开发之nio netty开发之nio netty开发之nio netty开发之nio netty开发之nio netty开发之nio netty开发之nio netty开发之nio netty开发之nio netty开发之nio netty开发之nio netty...
Mina2与Netty4是两种非常流行的网络编程框架,它们都用于构建高性能的网络服务器和客户端。由于它们都是基于Java NIO实现,因此有很多共同点,但同时也存在一些重要的差异。接下来将根据标题和描述的要求详细分析...
- **高性能**:Netty利用NIO(非阻塞IO)技术实现了高吞吐量和低延迟。 - **灵活**:提供了一种灵活的API来处理各种网络协议。 - **易于使用**:具有清晰的文档和广泛的社区支持。 - **跨平台**:可以在任何支持Java...
### Netty源码剖析与NIO及Netty5各种RPC架构实战演练三部曲知识点解析 #### 一、Netty概述 Netty是一款基于Java NIO的高性能服务器端编程框架,用于快速开发可维护的网络应用程序。它简化了网络编程的复杂性,使...
【标题】"NIO+Netty5视频教程2018"揭示了两个核心主题:Netty框架的源码分析和基于NIO的RPC架构实战。这个教程旨在帮助Java开发者深入理解和应用NIO(Non-blocking Input/Output)技术以及Netty网络框架,尤其在构建...
NIO(Non-blocking Input/Output)和Netty框架是Java平台上的两个核心概念,它们极大地提升了网络应用的性能和效率。本篇文章将深入探讨NIO的基本原理和Netty框架的使用,帮助你从初学者逐渐晋升为高级开发者。 ...
Netty 是一个高性能、异步事件驱动的网络应用程序框架,用于快速开发可维护的高性能协议服务器和客户端。在“Netty性能测试”中,我们关注的是Netty在处理并发请求时的能力,以及它作为RPC(远程过程调用)框架的...
手写NIO和Netty意味着尝试从零开始实现这些功能,这可以帮助深入理解底层原理,但通常并不推荐,因为Netty已经经过了大量的优化和测试,而且社区支持强大,可以直接使用而无需重新造轮子。 总之,NIO是一种改进的I/...
在本文中,我们将深入探讨Java IO,并结合MINA和Netty这两个流行的网络编程框架进行分析。 首先,Java IO提供了丰富的类库,允许程序进行数据的读写操作,包括文件操作、流处理、序列化等。它基于流的概念,分为...