码农知识堂 - 1000bd
  •   Python
  •   PHP
  •   JS/TS
  •   JAVA
  •   C/C++
  •   C#
  •   GO
  •   Kotlin
  •   Swift
  • Netty—— 概念剖析(零拷贝)


    目录

      • 一、传统 IO 问题
        • 1.1、传统的 IO 将一个文件通过 socket 写出
        • 1.2、传统 IO的内部工作流程图解
        • 1.3、传统 IO的内部工作流程概述
        • 1.4、传统 IO的问题
      • 二、NIO 优化传统 IO
        • 2.1、通过 DirectByteBuffer 优化传统 IO
        • 2.2、NIO 优化的内部工作流程图解
        • 2.3、NIO 优化的内部工作流程概述
        • 2.4、NIO 优化的内部工作流程总结
      • 三、进一步优化(底层采用了 linux 2.1 后提供的 sendFile 方法)
        • 3.1、通过 transferTo/transferFrom优化
        • 3.2、优化的内部工作流程图解
        • 3.3、优化的内部工作流程概述
        • 3.4、优化的内部工作流程总结
      • 四、进一步优化(底层采用了 linux 2.4)
        • 4.1、优化的内部工作流程图解
        • 4.2、优化的内部工作流程概述
        • 4.3、优化的内部工作流程总结
      • 五、零拷贝的优点

    一、传统 IO 问题

    1.1、传统的 IO 将一个文件通过 socket 写出

    • 主要代码部分

      File f = new File("D:\\data.txt");
      RandomAccessFile file = new RandomAccessFile(file, "r");
      
      byte[] buf = new byte[(int)f.length()];
      file.read(buf);
      
      Socket socket = ...;
      socket.getOutputStream().write(buf);
      

    1.2、传统 IO的内部工作流程图解

    • 内部工作流程图解

      在这里插入图片描述

    1.3、传统 IO的内部工作流程概述

    • java 本身并不具备 IO 读写能力,因此 read 方法调用后,要从 java 程序的用户态切换至内核态,去调用操作系统(Kernel)的读能力,将数据读入内核缓冲区。这期间用户线程阻塞,操作系统使用 DMA(Direct Memory Access)(DMA 也可以理解为硬件单元,用来解放 cpu 完成文件 IO)来实现文件读,其间也不会使用 cpu。
    • 从内核态切换回用户态,将数据从内核缓冲区读入用户缓冲区(即 byte[] buf),这期间 cpu 会参与拷贝,无法利用 DMA。
    • 调用 write 方法,这时将数据从用户缓冲区(byte[] buf)写入 socket 缓冲区,cpu 会参与拷贝。
    • 接下来要向网卡写数据,这项能力 java 又不具备,因此又得从用户态切换至内核态,调用操作系统的写能力,使用 DMA 将 socket 缓冲区的数据写入网卡,不会使用 cpu。

    1.4、传统 IO的问题

    • 从上述工程流程概述中可以看到中间环节较多,java 的 IO 实际不是物理设备级别的读写,而是缓存的复制,底层的真正读写是操作系统来完成的:
    • 用户态与内核态的切换发生了 3 次,这个操作比较重量级。
    • 数据拷贝了共 4 次。

    二、NIO 优化传统 IO

    2.1、通过 DirectByteBuffer 优化传统 IO

    • ByteBuffer.allocate(10) 返回值HeapByteBuffer, 使用的还是 java 内存。
    • ByteBuffer.allocate(10) 返回值HeapByteBuffer, 使用的是操作系统内存。

    2.2、NIO 优化的内部工作流程图解

    在这里插入图片描述

    2.3、NIO 优化的内部工作流程概述

    • 大部分步骤与1.3小节相同,不再赘述。唯有优点:java 可以使用 DirectByteBuffer 将堆外内存映射到 jvm 内存中来直接访问使用。
    • 这块内存不受 jvm 垃圾回收的影响,因此内存地址固定,有助于 IO 读写;
    • java 中的 DirectByteBuffer 对象仅维护了此内存的虚引用,内存回收分成两步:
      (1)、DirectByteBuffer 对象被垃圾回收,将虚引用加入引用队列;
      (2)、通过专门线程访问引用队列,根据虚引用释放堆外内存。

    2.4、NIO 优化的内部工作流程总结

    • 减少了一次数据拷贝,用户态与内核态的切换次数没有减少

    三、进一步优化(底层采用了 linux 2.1 后提供的 sendFile 方法)

    3.1、通过 transferTo/transferFrom优化

    • java 中对应着两个 channel 调用 transferTo/transferFrom 方法拷贝数据。

    3.2、优化的内部工作流程图解

    • 内部工作流程图解

      在这里插入图片描述

    3.3、优化的内部工作流程概述

    • java 调用 transferTo 方法后,要从 java 程序的用户态切换至内核态,使用 DMA将数据读入内核缓冲区,不会使用 cpu。
    • 数据从内核缓冲区传输到 socket 缓冲区,cpu 会参与拷贝。
    • 最后使用 DMA 将 socket 缓冲区的数据写入网卡,不会使用 cpu。

    3.4、优化的内部工作流程总结

    • 只发生了一次用户态与内核态的切换。
    • 数据拷贝了 3 次。

    四、进一步优化(底层采用了 linux 2.4)

    4.1、优化的内部工作流程图解

    • 内部工作流程图解
      在这里插入图片描述

    4.2、优化的内部工作流程概述

    • java 调用 transferTo 方法后,要从 java 程序的用户态切换至内核态,使用 DMA将数据读入内核缓冲区,不会使用 cpu。
    • 只会将一些 offset 和 length 信息拷入 socket 缓冲区,几乎无消耗。
    • 使用 DMA 将 内核缓冲区的数据写入网卡,不会使用 cpu。

    4.3、优化的内部工作流程总结

    • 整个过程仅只发生了一次用户态与内核态的切换,数据拷贝了 2 次。所谓的【零拷贝】,并不是真正无拷贝,而是在不会拷贝重复数据到 jvm 内存中。

    五、零拷贝的优点

    • 更少的用户态与内核态的切换。
    • 不利用 cpu 计算,减少 cpu 缓存伪共享。
    • 零拷贝适合小文件传输。
  • 相关阅读:
    自媒体新人,如何快速积累粉丝,我的业余Python能帮助我干些什么
    【集训DAY N】词典【暴力】【字典树】
    HCL模拟器下做M-LAG测试(以及和华为配置对比)-二层架构
    C语言知识之字符串
    C++~结构体/类的对齐规则详解,为什么要对齐
    练习副“产品”:自制七彩提示字符串展示工具(for循环、if条件判断)
    Python学习笔记(2)
    I2C总线 | I2C总线介绍
    Flutter | Stack 超出部分不响应手势的独特解决方案
    python的datetime模块常用的语法和实例
  • 原文地址:https://blog.csdn.net/li1325169021/article/details/127043537
  • 最新文章
  • 【JVM】编译执行与解释执行的区别是什么?JVM 使用哪种方式?
    用 Hashids 优雅解决 C 端自增 ID 暴露问题
    V8引擎 精品漫游指南--Ignition篇(上) 指令 栈帧 槽位 调用约定 内存布局 基础内容
    LLVM Pass快速入门(四):代码插桩
    milkup:桌面端 markdown AI续写和即时渲染
    基于项目工程构建SBOM(软件物料清单)的研究
    鸿蒙应用开发UI基础第二节:鸿蒙应用程序框架核心解析与实操
    .NET 中如何快速实现 List 集合去重?
    扣子Coze实战:从0到1打造抖音+小红书热点监控智能体
    浅谈数据访问层
  • 热门文章
  • 十款代码表白小特效 一个比一个浪漫 赶紧收藏起来吧!!!
    奉劝各位学弟学妹们,该打造你的技术影响力了!
    五年了,我在 CSDN 的两个一百万。
    Java俄罗斯方块,老程序员花了一个周末,连接中学年代!
    面试官都震惊,你这网络基础可以啊!
    你真的会用百度吗?我不信 — 那些不为人知的搜索引擎语法
    心情不好的时候,用 Python 画棵樱花树送给自己吧
    通宵一晚做出来的一款类似CS的第一人称射击游戏Demo!原来做游戏也不是很难,连憨憨学妹都学会了!
    13 万字 C 语言从入门到精通保姆级教程2021 年版
    10行代码集2000张美女图,Python爬虫120例,再上征途
小工具 小游戏
Copyright © 2022 侵权请联系2656653265@qq.com    京ICP备2022015340号-1

京公网安备 11010502049817号