IO高性能优化框架
-
提前读,预读 (减少读数据的时间)
-
延迟写(减少磁盘的次数)
-
优化物理块的分布,分片(减少磁臂移动距离)
-
临时文件(文件缓存,顺序读写减少磁臂移动距离)
-
内存映射(逻辑上属于磁盘, 物理上在内存中)
高性能IO操作方式
-
FileChannel使用的ByteBuffer一定要以4k的倍数操作
-
写入一定要加锁,不然并发时数据一定会错乱
-
保持顺序读或写操作(如果不能保持,请将文件分片后再保持顺序读写)
-
写入读取请使用堆外内存
-
复制内存请使用: 堆内System.arraycopy, 堆外unsafe.copyMemory
-
可以尝试使用DIO. https://github.com/smacke/jaydio
java.nio底层使用的类如下
核心包
-
sun.nio.ch (IO通道)
-
sun.nio.fs (文件系统)
类关系如下
-
父类 sun.nio.ch.NativeDispatcher
-
子类-文件 -> sun.nio.ch.FileDispatcherImpl
-
子类-TCP -> sun.nio.ch.SocketDispatcher
-
子类-UDP -> sun.nio.ch.DatagramDispatcher
IO拷贝的逻辑
-
NativeDispatcher接口
read write close(FileDescriptor, long address, int length) 读 写 关(文件句柄, 堆外内存地址, 读/写长度)
-
debug后可以看出,所有IO操作都是通过 sun.nio.ch.IOUtil操作的. IOUtil进行如下判断
如果是堆内内存,那么会将堆内内存转成堆外内存操作 转换会调用sun.nio.ch.Util.getTemporaryDirectBuffer(), 这个里面有ThreadLocal<Util.BufferCache> bufferCache 如果是堆外内存,不转换直接调用本地方法
-
总结 (所有IO操作都是用堆外内存操作的)
如果是堆内内存,会发生一次拷贝至堆外内存. 拷贝方式 -> System.arraycopy(堆外到堆内) 或 unsafe.copyMemory(堆内到堆外)