NIO vs. BIO
性能测试
测试方法
用同一个Java Socket Client 分别调用用BIO和NIO实现的Socket Server, 观察其建立一个Socket (TCP Connection)所需要的时间,从而计算出Server吞吐量TPS。
之所以可以用Connection建立时间来计算TPS,而不考虑业务逻辑运行时间,是因为这里的业务逻辑很简单,只是Echo回从client传过来的字符,所消耗时间可以忽略不计。
注意: 在现实场景中,业务逻辑会比较复杂,TPS的计算必须综合考虑IO时间+业务逻辑执行时间+多线程并行运行情况 等因素的影响。
测试类
1. Java Socket Client
public class PlainEchoClient {
public static void main(String args[]) throws Exception {
for (int i = 0; i < 20; i++) {
startClientThread();
}
}
private static void startClientThread() throws UnknownHostException,
IOException {
Thread t = new Thread(new Runnable() {
@Override
public void run() {
try {
startClient();
} catch (Exception e) {
e.printStackTrace();
}
}
});
t.start();
}
private static void startClient() throws UnknownHostException, IOException {
long beforeTime = System.nanoTime();
String host = "127.0.0.1";
int port = 8086;
Socket client = new Socket(host, port);
// 建立连接后就可以往服务端写数据了
Writer writer = new OutputStreamWriter(client.getOutputStream());
writer.write("Hello Server.");
writer.flush();
// 写完以后进行读操作
Reader reader = new InputStreamReader(client.getInputStream());
char chars[] = new char[64];// 假设所接收字符不超过64位,just for demo
int len = reader.read(chars);
StringBuffer sb = new StringBuffer();
sb.append(new String(chars, 0, len));
System.out.println("From server: " + sb);
writer.close();
reader.close();
client.close();
System.out.println("Client use time: "
+ (System.nanoTime() - beforeTime) + " ns");
}
}
2. IO Socket Server
这个Socket Server模拟的是我们经常使用的thread-per-connection模式, Tomcat,JBoss等Web Container都是这种方式。
public class PlainEchoServer {
private static final ExecutorService executorPool = Executors.newFixedThreadPool(5);
private static class Handler implements Runnable{
private Socket clientSocket;
public Handler(Socket clientSocket){
this.clientSocket = clientSocket;
}
@Override
public void run() {
try {
BufferedReader reader = new BufferedReader(
new InputStreamReader(
clientSocket.getInputStream()));
PrintWriter writer = new PrintWriter(
clientSocket.getOutputStream(), true);
char chars[] = new char[64];
int len = reader.read(chars);
StringBuffer sb = new StringBuffer();
sb.append(new String(chars, 0, len));
System.out.println("From client: " + sb);
writer.write(sb.toString());
writer.flush();
} catch (IOException e) {
e.printStackTrace();
try {
clientSocket.close();
} catch (IOException ex) {
// ignore on close
}
}
}
}
public void serve(int port) throws IOException {
final ServerSocket socket = new ServerSocket(port);
try {
while (true) {
long beforeTime = System.nanoTime();
final Socket clientSocket = socket.accept();
System.out.println("Establish connection time: "+ (System.nanoTime()-beforeTime)+" ns");
executorPool.execute(new Handler(clientSocket));
}
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) throws IOException{
PlainEchoServer server = new PlainEchoServer();
server.serve(8086);
}
}
3. NIO Socket Server
public class PlainNioEchoServer {
public void serve(int port) throws IOException {
ServerSocketChannel serverChannel = ServerSocketChannel.open();
ServerSocket ss = serverChannel.socket();
InetSocketAddress address = new InetSocketAddress(port);
ss.bind(address); // #1
serverChannel.configureBlocking(false);
Selector selector = Selector.open();
serverChannel.register(selector, SelectionKey.OP_ACCEPT); // #2
while (true) {
try {
selector.select(); // #3
} catch (IOException ex) {
ex.printStackTrace();
// handle in a proper way
break;
}
Set readyKeys = selector.selectedKeys(); // #4
Iterator iterator = readyKeys.iterator();
while (iterator.hasNext()) {
SelectionKey key = (SelectionKey) iterator.next();
try {
if (key.isAcceptable()) {
ServerSocketChannel server = (ServerSocketChannel) key
.channel();
long beforeTime = System.nanoTime();
SocketChannel client = server.accept(); // #6
System.out.println("Accept connection time: "+ (System.nanoTime()-beforeTime)+" ns");
if (client == null){//Check if socketChannel has been created, it could be null, because it's non-blocking
continue;
}
client.configureBlocking(false);
client.register(selector, SelectionKey.OP_WRITE
| SelectionKey.OP_READ,
ByteBuffer.allocate(100));
}
if (key.isReadable()) {
SocketChannel client = (SocketChannel) key.channel();
ByteBuffer output = (ByteBuffer) key.attachment();
client.read(output);
}
if (key.isWritable()) {
SocketChannel client = (SocketChannel) key.channel();
ByteBuffer output = (ByteBuffer) key.attachment();
output.flip();
client.write(output);
output.compact();
}
} catch (IOException ex) {
key.cancel();
try {
key.channel().close();
} catch (IOException cex) {
}
}
iterator.remove(); // #5
}
}
}
public static void main(String[] args) throws IOException{
PlainNioEchoServer server = new PlainNioEchoServer();
server.serve(8086);
}
}
测试结果
Establish connection time: 1523264 ns
Establish connection time: 1430883 ns
Accept connection time: 132927 ns
Accept connection time: 132413 ns
NIO还是BIO
BIO Server
NIO Server
什么时候使用BIO?
1. 低负载、低并发的应用程序可以选择同步阻塞IO以降低编程复杂度。
什么时候使用NIO?
版权声明:本文为博主原创文章,未经博主允许不得转载。
NIO vs. BIO的更多相关文章
- NIO 和BIO
讲讲NIO? 传统的IO流是阻塞式的,会一直监听一个ServerSocket,在调用read等方法时,他会一直等到数据到来或者缓冲区已满时才返回.调用accept也是一直阻塞到有客户端连接才会返回.每 ...
- AIO、NIO、BIO
AIO:异步非阻塞 NIO:同步非阻塞 BIO:同步阻塞 (1)同步 指的是用户进程触发IO操作并等待或者轮询的去查看IO操作是否就绪 (2)异步 指用户进程触发IO操作以后便开始做自己的事情,而当I ...
- 基于NIO和BIO的两种服务器对比
基于BIO的服务器,服务端可能要同时保持几百万个HTTP连接,而这些连接并不是每时每刻都在传输数据,所以这种情况不适合使用BIO的服务器:而且需要保证共享资源的同步与安全,这个实现起来相对复杂.这时候 ...
- nio、bio区别,应运场景
bio阻塞i/o a.面向流的,InputStream(),OuputStream字节输入流,字节输出流,Reader,Writer字符输入流,字符输出流 b.阻塞的IO,比如Socket,它的底层用 ...
- NIO、BIO、AIO区别
一.同步阻塞I/O(BIO): 同步阻塞I/O,服务器实现模式为一个连接一个线程,即客户端有连接请求时服务器就需要启动一个线程进行处理,如果这个连接不做任何事情会造成不必要的线程开销,可以通过线程池机 ...
- NIO,AIO,BIO
同步和异步:同步和异步关注的是消息通信机制, 同步:就是在发出一个“调用”时,在没有得到结果之前,该“调用”就不返回,但是一旦调用返回,就得到返回值了;换句话说:就是由“调用者”主动等待“调用”结果 ...
- java NIO、BIO、AIO全面剖析
在高性能的IO体系设计中,有几个名词概念常常会使我们感到迷惑不解.具体如下: 序号 问题 1 什么是同步? 2 什么是异步? 3 什么是阻塞? 4 什么是非阻塞? 5 什么是同步阻塞? 6 什么是同步 ...
- Java中NIO、BIO、AIO相关概念及应用场景
1.同步阻塞IO(JAVA BIO):同步并阻塞,服务器实现模式为一个连接一个线程,即客户端有连接请求时,服务器端就需要启动一个线程进行处理,如果这个连接不做任何事情会造成不必要的线程开销,当然可以通 ...
- Java IO、BIO、NIO、BIO
一.什么是IO/NIO: IO:即BIO(Blocking IO):面向流的.同步阻塞式IO:(JDK1.4之前唯一的选择) NIO:面向缓冲的.同步非阻塞式IO:三大核心部分:Selector.Ch ...
随机推荐
- Java项目往数据库中插入数据,出现中文乱码
项目环境: JSP+Servlet+Mysql数据库 需要检查的地方: 1. java项目整体的编码格式为utf-8.并且将数据传递给数据库之前,数据是否依旧是正常的(可以通过打断点的方式一步步跟踪查 ...
- 1.5 Eclipse集成开发环境
1. 格式化nandflash PATH路径优先用前面的 Arm-linux-gdb # .bashrc # User specific aliases and functions ali ...
- Access数据库的模糊查询到底是用*还是%
今天被用了一下Access数据库,结果被它的模糊查询给折腾了一上午,到底是用*还是%?特此记下来 事情是这样的,我用C#写了个小的窗体程序,访问Access数据库进行一个模糊查询,我先手工往Acces ...
- 基础连接已经关闭: 未能为 SSL/TLS 安全通道建立信任关系。
(转自:http://blog.sina.com.cn/s/blog_5eca668b01018949.html)定义一个类,来对远程X.509证书的验证,进行处理,返回为true.我们要自己定义一个 ...
- Vagrant+virtualBox+pycham+python环境的安装及配置
概要: 通过Vagrant,virtualBox安装配置,把virtualBox虚拟机的linux项目映射windows本地项目中,在windows的pycharm工具中开发用python语言开发项目 ...
- oracle-关于dual
来源:百度知道1. dual 是一张表.是一张只有一个字段,一行记录的表. 2.习惯上,我们称之为'伪表'.因为他不存储主题数据.3. 他的存在,是为了操作上的方便.因为select 都是要有特定对象 ...
- leetcode174. Dungeon Game
// learn from https://discuss.leetcode.com/topic/6912/c-dp-solution ''' class Solution { public: int ...
- 初探VIM编辑器
初探VIM 引言---什么是Vim? 接触Linux这么久,想必对于一切皆文件的哲学思想已经不陌生了.因此,学习并掌握用一款Linux文本编辑器,对于玩转LInux来说,是很有必要的. vi编辑器是U ...
- 冲刺一 (Day 3)
冲刺一 (Day 3) 用户表 uid int 8 用户ID username varchar 20 用户名 password varchar 20 密码 email varchar 30 邮箱 ph ...
- Git分支的前世今生
摘自Jack__CJ CSDN博客,写得很好,保存一下. 导读 几乎所有的版本控制系统都以某种形式支持分支. 使用分支意味着你可以把你的工作从开发主线上分离开来,以免影响开发主线. 在很多版本控制系 ...