NIO vs BIO模型解读

news2024/12/24 10:47:03

目录

stream vs channel

IO模型

零拷贝

传统IO

NIO优化


stream vs channel

  • stream 不会自动缓冲数据,channel 会利用系统提供的发送缓冲区、接收缓冲区(更为底层)
  • stream 仅支持阻塞 API,channel 同时支持阻塞、非阻塞 API,网络 channel 可配合 selector 实现多路复用
  • 二者均为全双工,即读写可以同时进行

IO模型

同步阻塞、同步非阻塞、同步多路复用、异步阻塞(没有此情况)、异步非阻塞

  • 同步:线程自己去获取结果(一个线程)
  • 异步:线程自己不去获取结果,而是由其它线程送结果(至少两个线程)

当调用一次 channel.read 或 stream.read 后,会切换至操作系统内核态来完成真正数据读取,而读取又分为两个阶段,分别为:

  • 等待数据阶段
  • 复制数据阶段

阻塞 IO

 非阻塞 IO

多路复用

异步 IO

通过 DirectByteBuf

  • ByteBuffer.allocate(10) HeapByteBuffer 使用的还是 java 内存
  • ByteBuffer.allocateDirect(10) DirectByteBuffer 使用的是操作系统内存

零拷贝

传统IO

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

File f = new File("helloword/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. java 本身并不具备 IO 读写能力,因此 read 方法调用后,要从 java 程序的用户态切换至内核态,去调用操作系统(Kernel)的读能力,将数据读入内核缓冲区这期间用户线程阻塞,操作系统使用 DMA(Direct Memory Access)来实现文件读,其间也不会使用 cpu

    DMA 也可以理解为硬件单元,用来解放 cpu 完成文件 IO

  2. 内核态切换回用户态,将数据从内核缓冲区读入用户缓冲区(即 byte[] buf),这期间 cpu 会参与拷贝,无法利用 DMA

  3. 调用 write 方法,这时将数据从用户缓冲区(byte[] buf)写入 socket 缓冲区,cpu 会参与拷贝

  4. 接下来要向网卡写数据,这项能力 java 又不具备,因此又得从用户态切换至内核态,调用操作系统的写能力,使用 DMA 将 socket 缓冲区的数据写入网卡,不会使用 cpu

可以看到中间环节较多,java 的 IO 实际不是物理设备级别的读写,而是缓存的复制,底层的真正读写是操作系统来完成的

  • 用户态与内核态的切换发生了 3 次,这个操作比较重量级
  • 数据拷贝了共 4 次

NIO优化

通过 DirectByteBuf

  • ByteBuffer.allocate(10) HeapByteBuffer 使用的还是 java 内存
  • ByteBuffer.allocateDirect(10) DirectByteBuffer 使用的是操作系统内存

 大部分步骤与优化前相同,不再赘述。唯有一点:java 可以使用 DirectByteBuf 将堆外内存映射到 jvm 内存中来直接访问使用

堆外内存与堆内内存相对应,对于整个机器内存而言,除堆内内存以外部分即为堆外内存。属于用户空间。直接使用堆外内存可以减少一次内存拷贝: 当进行网络 I/O 操作、文件读写时,堆内内存都需要转换为堆外内存,然后再与底层设备进行交互。

  • 这块内存不受 jvm 垃圾回收的影响,因此内存地址固定,有助于 IO 读写
  • java 中的 DirectByteBuf 对象仅维护了此内存的虚引用,内存回收分成两步
    • DirectByteBuf 对象被垃圾回收,将虚引用加入引用队列
    • 通过专门线程访问引用队列,根据虚引用释放堆外内存
  • 减少了一次数据拷贝,用户态与内核态的切换次数没有减少

进一步优化(底层采用了 linux 2.1 后提供的 sendFile 方法),java 中对应着两个 channel 调用 transferTo/transferFrom 方法拷贝数据

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

进一步优化(linux 2.4)

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

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

  • 更少的用户态与内核态的切换
  • 不利用 cpu 计算,减少 cpu 缓存伪共享
  • 零拷贝适合小文件传输

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/604089.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

计算机网络-网络层1.1

IPv4 网络层打包传输数据时,数据量小则称IP数据报,数据量大则分片,每一片称为IPv4分组 分组格式 固定部分长20B,可变部分用于提供错误检测和安全等机制 版本:指IP版本首部长度:以4B为单位&#xff0c…

Java --- springboot3之web的自动配置原理

目录 一、自动配置 二、默认效果 三、WebMvcAutoConfiguration原理 3.1、生效条件 3.2、效果 3.3、WebMvcConfigurer接口 一、自动配置 1、导入web的pom依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-s…

计算机网络-层级架构

计网概念 计算机网络将分散的、具有独立功能的计算机系统&#xff0c;通过通信设备与线路连接起来&#xff0c;由软件实现资源共享和信息传递&#xff0c;同时也是一些互联的、自治的计算机系统的集合 计网组成的三种划分方式 硬件、软件、协议 硬件包含主机&#xff08;端系…

Redis底层学习(四)—存储类型-Hash篇

文章目录 特点具体服务器操作命令底层结构应用场景 特点 1.适⽤场景&#xff1a;存储⽆序字典的数据&#xff0c;⽐如&#xff1a;适合存储对象类型、存储猪⾁价格等。 2.它的内部采⽤ 数组 链表 的结构&#xff0c;类似java⾥的HashMap。 hash的key值只能是字符串。将对象存…

从C语言到C++_15(vector的模拟实现)+迭代器失效问题

目录 1. vector的基本框架 1.1 构造析构和容量 1.2 push_back&#xff0c;reserve和operator[ ] 2. vector的迭代器 2.1 四个基本迭代器 2.2 迭代器区间初始化 2.3 迭代器的分类 3. vector的其它接口函数 3.1 修改后的reserve 3.2 resize 3.3 pop_back 4. insert和…

【Android】Jadx动态调试应用

【Android】Jadx动态调试应用 1. 前言 Jadx已支持动态调试APP&#xff0c;但一直没试过&#xff0c;从逆向角度尝试走一遍流程并熟悉&#xff0c;方便日后翻阅。 2. 相关知识 2.1 动态调试原理 动态调试的原理可以概括为以下几个步骤&#xff1a; 启动应用程序进程&#x…

[数据挖掘02] pandas的分配和聚合函数(1)

一 说明 窗口函数是什么&#xff1f;窗口函数是时间序列的局部属性处理函数&#xff0c;比如&#xff0c;一维卷积滤波、移动平均、指数平均本篇我们将针对pandas对象的窗口函数展开讨论&#xff0c;并以示例展示他们的概念实质。 二 窗口函数、分组函数&#xff08; GroupBy …

2023年18个最佳的ChatGPT AI插件

​关注文章下方公众号&#xff0c;可免费获取AIGC最新学习资料 导读&#xff1a;ChatGPT已经将人工智能提升到了一个新的高度。ChatGPT 4不仅是聊天机器人&#xff0c;还可以很好地与第三方插件配合使用。我们挑选出了2023年目前18款最佳的插件来介绍给您。 本文字数&#xff…

【运维知识进阶篇】Ansible Jinja2模板详解

哈喽大家好&#xff0c;我是koten&#xff0c;本篇文章给大家介绍jinja2模板&#xff0c;这是python的全功能模板引擎。在Ansible中&#xff0c;通常会使用jinja2模板来修改被管理主机的配置文件&#xff08;saltstack中也会用到&#xff09; Ansible中使用的jinja2模板其实就…

【软件测试】软件测试管理

软件测试管理 软件测试环境测试环境的要素测试环境管理员 软件测试计划⭐测试计划目标测试计划主题测试计划制订过程定义工作进度的过程测试策略 软件缺陷(bug)管理缺陷的主要属性如何报告缺陷⭐如何跟踪缺陷缺陷度量 软件配置管理&#xff08;SCM&#xff09;软件配置管理的基…

计算机网络传输层1.0

功能 传输层提供进程到进程的逻辑通信 复用和分用 传输层对收到的报文进行差错检测 TCP/UDP 提供进程到进程的逻辑通信 网络层是提供主机间逻辑通信 从网络层来看&#xff0c;通信双方为两台主机&#xff0c;IP数据包首部给出两台主机的IP地址 而实际上的两台主机通信时两台…

Makefile路径处理:执行路径、绝对路径与相对路径的处理

问题描述 最近编写了一个 编译设备树 的 Makefile&#xff0c;遇到了使用 make -f xx/Makefile&#xff0c;执行路径变了&#xff0c;造成 Makefile 里面的一些操作路径不正确&#xff0c;无法执行 获取当前目录 make 内置的 $(CURDIR)&#xff0c;可以把当前路径的全路径打印…

Three.js--》实现图片转3D效果展示

目录 项目搭建 初始化three.js基础代码 加载图片纹理 设置着色器 今天简单实现一个three.js的小Demo&#xff0c;加强自己对three知识的掌握与学习&#xff0c;只有在项目中才能灵活将所学知识运用起来&#xff0c;话不多说直接开始。 项目搭建 本案例还是借助框架书写th…

逻辑推理与集合

逻辑推理与集合是同一个过程的不同展示方式&#xff0c;这两者具有不同的特点。 逻辑推理通常是一种思维过程、语言文本的形式。 而集合则很容易采用一种可视化的方式进行展示&#xff0c;并且集合很容易进行交集、并集、补集、差集等计算。 把语言的逻辑推理过程转换为集合…

0602-指针和数组

数组名 数组名是一个地址常量&#xff0c;不允许赋值。它表示数组首元素的地址。 指针操作数组元素 指针访问数组 指针类型变量\常量1等同于指针保存的内存地址sizeof(指针指向的数据类型)。 2个相同类型的指针相减&#xff0c;得到的结果是2个指针的偏移量。其中偏移单位…

STL模型转有限元网格

随着计算机图形学、硬件和3D打印技术的发展&#xff0c;基于曲面三角网格的图形渲染及其文件格式越来越流行。 在有限元分析&#xff08;FEA&#xff09;中&#xff0c;工程师有时会得到基于三角形网格的几何文件&#xff08;如STL文件等&#xff09;并进行后续分析。 由于曲面…

华为OD机试真题 Java 实现【检查是否存在满足条件的数字组合】【2022Q4 100分】

一、题目描述 给定一个正整数数组&#xff0c;检查数组中是否存在满足规则的数字组合 规则&#xff1a;A B 2C 二、输入描述 第一行输出数组的元素个数。 接下来一行输出所有数组元素&#xff0c;用空格隔开。 三、输出描述 如果存在满足要求的数&#xff0c;在同一行…

【MySQL】不允许你不会SQL语句之DDL

目录 前言&#xff1a; 一.DDL数据库语句 1.1语句讲解 1.2总结 二.DDL表语句 2.1语句讲解 2.2总结 三.DDL字段语句 3.1语句讲解 3.2总结 四.MySQL数据类型 五.结尾 前言&#xff1a; 在从零到一入门MySQL一篇中&#xff0c;我们对数据库已经有了一定的了解&#xf…

Linux 设备树手动反编译 dtb 生成 源文件dts

验证平台 win10 64 位 VMware Workstation Pro 16 ubuntu 20.04 dtc 工具&#xff1a; 来自 linux-6.3.5 中的 scripts/dtc/ 安装 dtc 工具 其实可以通过安装 dtc 软件包&#xff0c;但不建议这么做&#xff0c;最好通过编译Linux 最新的内核&#xff0c;获取这个 dtc 工具…

利用Web Serial API实现Vue与单片机串口通信

一、Web Serial API介绍 Web Serial API 是一项 Web 技术&#xff0c;用于在浏览器中访问串行端口设备&#xff08;如 Arduino、传感器等&#xff09;并与之通信。它提供了一组 JavaScript 接口&#xff0c;使得 Web 应用程序可以通过 USB 串行端口连接到硬件设备&#xff0c;并…