前些日了,对AIO与NIO的并发性能进行了比较,在低并发的情况下,NIO性能表现比AIO好一些,主要原因是,NIO中可以使用FileChannel.transferTo(long position, long count, WritableByteChannel target),这个方法可以对传输文件数据有很大的性能提升。

在AIO中,没办法使用FileChannel.transferTo(...),只能使用ByteBuffer来做中转,我一开始使用的ByteBuffer.allocate(16 * 1024),也就是16KB的缓存区。

由于上面的原因,所以NIO在不是很高的并发情况下,性能比AIO表现的好一些。

昨天,我还写了一篇文章:AsynchronousFileChannel 使用的默认线程池的疑问

今天早上,我试着将ByteBuffer由原来固定的16KB,更改为一个与传输的文件大小有关的字节缓存区。

相关代码如下:

//如果文件大小<1M,直接返回一个 fileSize + headerSize
 //如果文件大小>=1M,直接返回一个(fileSize + headerSize) / 2, 也就是最多保证分两次传输完数据
 private ByteBuffer allocateByteBuffer(int fileSize, int headerSize)
 {
  if(fileSize < 1024 * 1024)
  {
   return ByteBuffer.allocate(fileSize + headerSize);
  }
  else
  {
   return ByteBuffer.allocate((fileSize + headerSize) / 2 + 1); //这所以 +1, 因为 11 / 2 = 5,为了保证两次传完, + 1 可保证这一点
  }
 }

然后经过测试发现,在低并发情况下,性能上升了很多,终于赶上了NIO的性能,同时观察“任务管理器”中的进程使用的线程数也下降了很多,真是一举两得,这让我兴奋了好一会儿,

经过冷静的分析,我得出的结论:

之所以将ByteBuffer的大小设置为与传输的文件大小有关的缓存区后性能得到了很大的提升,主要与AIO的“写操作”有关。

举个例子:

在AIO的“写操作”中,如果我们设置ByteBuffer为一个固定的16KB的缓存区,当我们传输一个160KB的文件时,AIO的“写操作”需要执行10次“回调”。每1次的回调都是在系统默认的一个线程池中运行的,回调的次数与线程池中的线程数是成正比的。

如是我们将ByteBuffer设置为160KB,在进行AIO的“写操作”时,系统只执行了一次“回调”,回调的次数减少了,线程池的容量也不再需要那么多了,性能同时也上升了。

不过,经过测试也发现,ByteBuffer的容量也不能无限制的根据文件大小一设置,如果一个文件超过1M,还是最好设置为最大不超过1M的缓存区比较好,因为测试发现,如果设置一个很大的缓存区,比如5M,在高并发的时候,系统内存会很快用完,直接抛出: OutOfMemoryError

-------------------------------------------------------------------------------------------------

AIO进程占用的线程数与文件IO和网络IO有非常大的关系,当高并发的时候,网络IO达到瓶颈,这个时候很多任务都没有完成(正在完成中),占用的线程自然就会不断的上升。

2012-07-10

最新文章

  1. opencv_haar分类器的训练
  2. .Net自带缓存Cache的使用
  3. Codeforces 653D Delivery Bears(最大流)
  4. 自定义Property属性动画
  5. Java学习-010-创建文件夹源代码
  6. java程序(一)----HashMap同时获取键值
  7. Delphi For Android 开发笔记-附:如何Delphi中同时实现Windows、Android版的GetModuleFileName函数
  8. Textures
  9. myeclipse 8.5安装freemarker插件方法
  10. JavaScript: top对象
  11. Centos6 下启动httpd报错 Could not reliably determine the server&#39;s解决方法
  12. 解决外网与内网或内网之间的通信,NAT穿透
  13. linux_Ubuntu 12.04 安装jdk
  14. ubuntu12.04下编译chrome
  15. 【BZOJ4556】字符串(后缀数组,主席树)
  16. Alpha冲刺No.2
  17. Linux 实例常用内核网络参数介绍与常见问题处理
  18. Java的get、post请求
  19. Javascript基础语法(三)
  20. 剑指Offer 44. 翻转单词顺序列 (字符串)

热门文章

  1. maven中添加jetty运行插件
  2. 【第三方插件】使用Topshelf创建Windows服务
  3. EZ 2018 05 13 NOIP2018 模拟赛(十三)
  4. 汇编 fsub ,fmul,fdiv,fild,CVTTPS2PI 指令
  5. 汇编  cdecl 函数调用约定,stdcall 函数调用约定
  6. pt-online-schema-change的实现原理
  7. 3Sum(or k_Sum)
  8. 20135202闫佳歆--week2 一个简单的时间片轮转多道程序内核代码及分析
  9. 《Linux内核设计与实现》第18章读书整理
  10. 20135220谈愈敏Linux Book_1&amp;2