java NIO引用自http://blog.csdn.net/shidcai/archive/2006/03/19/629261.aspx
2006-03-20 18:22
597 查看
为了实现高性能的MOM(消息中间件),学习了java的NIO,想利用NIO技术来改善网络通讯的性能。学习NIO的时候,看了书上的,也找了网上相当 多的资源,但大部分的资料都是比较粗浅的,入门级,深入的基本没有。不过,对于了解和学习NIO来说已经足够了。真正的领会还是需要在实践中获得的。
NIO的技术在JDK1.4中出现。NIO最大的特点有两个:一个是块状读写;另外一个是多路复用技术(multiplex)。第一个特点改变了老式IO 中,每次读写只有一个字节(stream)和两个字节(reader)的方式,提高了读写的速度;第二个特点改变了原来读写socket时候阻塞的同步状 况,使socket的读写具有的异步的功能。第二个特点比较重要,NIO的异步读写据说大大提高了网络通讯的能力,尽管没有C++的快,但至少不再象以前 那样,一说起java首先想到的是“性能低下”。这一点,在网上可以搜到一大把的资料。
在JTangMQ消息中间件中,使用了NIO实现了通讯层。为了方便起见,客户端和服务器都采用了同一块代码,也就是说,客户端和服务器端都是非阻塞的, 编解码和读写socket的方式都一样。然而,在测试过程中发现,客户端在向服务器发送消息的时候,cpu的占用率在80%左右,带宽只占了5% (100M的带宽);服务器端的配置比较高,cpu的占用率在10%左右,带宽占有率一样。通过java的profiler工具分析,发现客户端的cpu 时间主要是消耗在选择器的select操作之上(NIO的多路复用),而select操作主要调用的是poll函数,这个函数是sun公司提供的关于选择 器的缺省类。根据网上的资料,这个操作是一个轮询socket的同步操作,它的主要功能就是不断地去查询向该选择器注册的socket,看看有没有可做的 操作,如有,则返回,没有,继续不断地轮询。也就说,分配的cpu的时间基本上被消耗在poll上了。
现在问题就出来了。既然poll占用这么多时间,是因为没有什么东西可以写入socket或者从socket中读取;那么,就应该给“提供读写数据的线 程”更多的cpu时间,使得每一次的poll都有可作的操作,使时间耗费在读写socket之上,而不是poll之上。然而,从分析数据中看来,poll 线程显然比“提供读写数据的线程(wr线程)”占用了更多的cpu时间,假设他们的优先级相同,也假设操作系统是公平的分配cpu时间,那么它们得到的 cpu时间应该是一样的,此时,造成它们占用cpu时间不同的原因就很可能是这样:在相同的时间内,wr线程提供的数据量根本不够poll线程处理, poll线程处理在相同的时间内处理这些数据绰绰有余,那么,poll线程更多的时间就耗费在轮询上了。到这里,我们假设的是这两个线程分配到了相同的时 间,所以,即使poll线程大部分时间是在做poll轮询操作,那么所占用的时间最大值也是有限的,不会超过线程分配得到的时间。但是,如果此时尽管wr 线程得到了cpu时间,但是它在处理过程中主动放弃cpu(比如执行wait操作),那么,在cpu时间总量相等的情况下,由于poll线程没有执行 wait操作,因此,就会得到更多的cpu时间,这样,就会出现上面的分析的情况,大部分的cpu时间都给poll的轮询操作了。
由此分析,如果使wr线程不断的运行,而使poll线程在没有数据的时候放弃cpu时间,就应该可以减少poll线程的轮询操作,而使wr线程得到更多 的cpu时间,提供更多的可供读写的数据,提高读写的效率。然而,由于poll轮询操作是一个不间断的过程,是sun公司提供的底层的api,是无法修改 的。所以,就要放弃poll操作,也就是要放弃选择器。换句话说,就是客户端最好是不要采用非阻塞的方式。
综上所分析,如果客户端采用非阻塞的方式, 应该是可以提高客户端读写socket的速度的。而服务器端由于要同时连接大量的客户端,还是继续采用非阻塞方式为好。
这只是分析的结果,还没有具体实验过。不知道有没有人遇到过类似的问题,请不吝赐教。
NIO的技术在JDK1.4中出现。NIO最大的特点有两个:一个是块状读写;另外一个是多路复用技术(multiplex)。第一个特点改变了老式IO 中,每次读写只有一个字节(stream)和两个字节(reader)的方式,提高了读写的速度;第二个特点改变了原来读写socket时候阻塞的同步状 况,使socket的读写具有的异步的功能。第二个特点比较重要,NIO的异步读写据说大大提高了网络通讯的能力,尽管没有C++的快,但至少不再象以前 那样,一说起java首先想到的是“性能低下”。这一点,在网上可以搜到一大把的资料。
在JTangMQ消息中间件中,使用了NIO实现了通讯层。为了方便起见,客户端和服务器都采用了同一块代码,也就是说,客户端和服务器端都是非阻塞的, 编解码和读写socket的方式都一样。然而,在测试过程中发现,客户端在向服务器发送消息的时候,cpu的占用率在80%左右,带宽只占了5% (100M的带宽);服务器端的配置比较高,cpu的占用率在10%左右,带宽占有率一样。通过java的profiler工具分析,发现客户端的cpu 时间主要是消耗在选择器的select操作之上(NIO的多路复用),而select操作主要调用的是poll函数,这个函数是sun公司提供的关于选择 器的缺省类。根据网上的资料,这个操作是一个轮询socket的同步操作,它的主要功能就是不断地去查询向该选择器注册的socket,看看有没有可做的 操作,如有,则返回,没有,继续不断地轮询。也就说,分配的cpu的时间基本上被消耗在poll上了。
现在问题就出来了。既然poll占用这么多时间,是因为没有什么东西可以写入socket或者从socket中读取;那么,就应该给“提供读写数据的线 程”更多的cpu时间,使得每一次的poll都有可作的操作,使时间耗费在读写socket之上,而不是poll之上。然而,从分析数据中看来,poll 线程显然比“提供读写数据的线程(wr线程)”占用了更多的cpu时间,假设他们的优先级相同,也假设操作系统是公平的分配cpu时间,那么它们得到的 cpu时间应该是一样的,此时,造成它们占用cpu时间不同的原因就很可能是这样:在相同的时间内,wr线程提供的数据量根本不够poll线程处理, poll线程处理在相同的时间内处理这些数据绰绰有余,那么,poll线程更多的时间就耗费在轮询上了。到这里,我们假设的是这两个线程分配到了相同的时 间,所以,即使poll线程大部分时间是在做poll轮询操作,那么所占用的时间最大值也是有限的,不会超过线程分配得到的时间。但是,如果此时尽管wr 线程得到了cpu时间,但是它在处理过程中主动放弃cpu(比如执行wait操作),那么,在cpu时间总量相等的情况下,由于poll线程没有执行 wait操作,因此,就会得到更多的cpu时间,这样,就会出现上面的分析的情况,大部分的cpu时间都给poll的轮询操作了。
由此分析,如果使wr线程不断的运行,而使poll线程在没有数据的时候放弃cpu时间,就应该可以减少poll线程的轮询操作,而使wr线程得到更多 的cpu时间,提供更多的可供读写的数据,提高读写的效率。然而,由于poll轮询操作是一个不间断的过程,是sun公司提供的底层的api,是无法修改 的。所以,就要放弃poll操作,也就是要放弃选择器。换句话说,就是客户端最好是不要采用非阻塞的方式。
综上所分析,如果客户端采用非阻塞的方式, 应该是可以提高客户端读写socket的速度的。而服务器端由于要同时连接大量的客户端,还是继续采用非阻塞方式为好。
这只是分析的结果,还没有具体实验过。不知道有没有人遇到过类似的问题,请不吝赐教。
相关文章推荐
- ICTCLAS分词系统Java调用接口在Eclipse中的安装 http://blog.csdn.net/CloneIQ/archive/2006/07/20/945909.aspx
- java关键字Transient 转自:http://blog.csdn.net/flynetcn/archive/2008/03/03/2142020.aspx
- 在基于Struts构架的Java Web项目中加入ICTCLAS分词http://blog.csdn.net/CloneIQ/archive/2006/08/09/1043088.aspx
- Eclipse Java注释模板设置详解 http://blog.csdn.net/ahhsxy/archive/2009/09/11/4542682.aspx
- JAVA中数据库操作的各种方式与设计模式的应用(http://blog.csdn.net/wangyihust/archive/2006/01/14/579613.aspx)
- ASP.NET 常用技巧学习 (http://blog.csdn.net/JavaProgramers/archive/2007/04/13/1563441.aspx)
- 如何将Web应用打包成.war文件? 转自:http://blog.csdn.net/code_JAVA/archive/2008/05/19/2457749.aspx
- java annotation---摘自http://blog.csdn.net/numenZQ/archive/2007/06/17/1654827.aspx
- LTE网络节点,接口,协议栈 引用 http://blog.csdn.net/yanghehong/archive/2009/02/15/3894307.aspx
- ant 介绍 http://blog.csdn.net/sunjavaduke/archive/2007/03/08/1523819.aspx
- Java字符编码 --摘自http://blog.csdn.net/numenZQ/archive/2007/06/17/1654827.aspx
- Eclipse_jboss00(http://blog.csdn.net/javamxj/archive/2005/01/13/251982.aspx)
- Mysql 基本操作 引用:http://www.blogjava.net/TrampEagle/archive/2006/01/07/26978.html
- java中的数组与集合的排序---摘抄自:http://blog.csdn.net/jonathan_q_bo/archive/2005/11/29/539043.aspx
- java的内存泄露(转自:http://blog.csdn.net/elimago/archive/2007/12/18/1946380.aspx)
- vs2005使用记趣(引用于http://blog.csdn.net/flyingjsj/archive/2008/08/02/2756496.aspx)
- 数据同步算法研究 ( 好博客) http://blog.csdn.net/liuben/archive/2010/08/06/5793706.aspx
- WSDL: 描述你的Web服务(转载http://blog.csdn.net/flyingBox/archive/2006/01/01/568162.aspx)
- Ext2.0框架的Grid使用介绍--转载http://blog.csdn.net/chiangbt/archive/2008/01/24/2064117.aspx
- Invalid postback or callback argument. (转http://blog.csdn.net/Alionkun/archive/2009/11/22/4853437.aspx)