零拷贝

简介: 实现文件传输时,若采用传统read/write方式,每32KB需两次系统调用,引发4次上下文切换,1万次共4万次切换,性能低下。主因是频繁的用户态与内核态切换开销大,且数据需经内存缓冲中转。可优化为使用零拷贝技术(如sendfile),减少数据复制和上下文切换,提升传输效率。

服务器提供文件传输功能,需要将磁盘上的文件读取出来,通过网络协议发送到客户端。如果需要你自己编码实现这个文件传输功能,你会怎么实现呢?

通常,你会选择最直接的方法:从网络请求中找出文件在磁盘中的路径后,如果这个文件比较大,假设有 320MB,可以在内存中分配 32KB 的缓冲区,再把文件分成一万份,每份只有 32KB,这样,从文件的起始位置读入 32KB 到缓冲区,再通过网络 API 把这 32KB 发送到客户端。接着重复一万次,直到把完整的文件都发送完毕。
不过这个方案性能并不好,主要有两个原因。

首先,它至少经历了 4 万次用户态与内核态的上下文切换。因为每处理 32KB 的消息,就需要一次 read 调用和一次 write 调用,每次系统调用都得先从用户态切换到内核态,等内核完成任务后,再从内核态切换回用户态。可见,每处理 32KB,就有 4 次上下文切换,重复 1 万次后就有 4 万次切换。

这个系统调用的内容,我们可以结合下面补充的三种“上下文切换”来理解,上下文切换分别是进程,线程,中断三种。

补充:进程上下文切换
Linux 按照特权等级,把进程的运行空间分为内核空间和用户空间,分别对应着下图中, CPU 特权等级的 Ring 0 和 Ring 3。内核空间(Ring 0)具有最高权限,可以直接访问所有资源,而用户空间(Ring 3)只能访问受限资源,不能直接访问内存等硬件设备,必须通过系统调用陷入到内核中,才能访问这些特权资源。换个角度看,也就是说,进程既可以在用户空间运行,又可以在内核空间中运行。进程在用户空间运行时,被称为进程的用户态,而陷入内核空间的时候,被称为进程的内核态。从用户态到内核态的转变,需要通过系统调用来完成。比如,当我们查看文件内容时,就需要多次系统调用来完成:首先调用 open() 打开文件,然后调用 read() 读取文件内容,并调用 write() 将内容写到标准输出,最后再调用 close() 关闭文件。
那么系统调用的过程是如何发生 CPU 上下文的切换的呢?我们再了解两个概念:

  1. CPU 寄存器,是 CPU 内置的容量小、但速度极快的内存。
  2. 程序计数器,则是用来存储 CPU 正在执行的指令位置、或者即将执行的下一条指令位置。它们都是 CPU 在运行任何任务前,必须的依赖环境,因此也被叫做 CPU 上下文。
    知道了什么是 CPU 上下文,我想你也很容易理解 CPU 上下文切换。CPU 上下文切换,就是先把前一个任务的 CPU 上下文(也就是 CPU 寄存器和程序计数器)保存起来,然后加载新任务的上下文到这些寄存器和程序计数器,最后再跳转到程序计数器所指的新位置,运行新任务。而这些保存下来的上下文,会存储在系统内核中,并在任务重新调度执行时再次加载进来。这样就能保证任务原来的状态不受影响,让任务看起来还是连续运行。

回到系统调用的问题上,CPU 寄存器里原来用户态的指令位置,需要先保存起来。接着,为了执行内核态代码,CPU 寄存器需要更新为内核态指令的新位置。最后才是跳转到内核态运行内核任务。而系统调用结束后,CPU 寄存器需要恢复原来保存的用户态,然后再切换到用户空间,继续运行进程。所以,一次系统调用的过程,其实是发生了两次 CPU 上下文切换。

相关文章
|
26天前
|
存储 Java
One Trick Per Day
初始化Map时应避免直接指定容量,建议使用Guava的`Maps.newHashMapWithExpectedSize()`或手动计算初始容量(如:目标大小 / 0.75 + 1),以防扩容开销。禁止使用Executors创建线程池,因其默认队列无界或线程数无限制,易引发OOM。推荐通过ThreadPoolExecutor显式构造,控制资源使用。
|
26天前
|
测试技术 Nacos 开发者
从Google线上故障,谈灰度发布的重要性2
业务配置灰度可通过主流配置中心实现,如Nacos支持IP和标签灰度,可扩展SPI定制策略;Apollo仅支持IP灰度,二者均可二次开发。复杂场景可基于Nacos标签扩展或自研方案,多数场景推荐使用Nacos满足需求。
|
26天前
|
存储 人工智能 搜索推荐
向量数据库的基本概念
向量数据库是专为存储和检索高维向量设计的系统,能将图片、文本等非结构化数据转化为“数字指纹”(向量),通过相似性搜索快速找到相近内容,广泛应用于推荐系统、图像识别和AI搜索等领域。
|
26天前
|
人工智能 JSON 安全
大模型应用开发中MCP与Function Call的关系与区别
Function Call依赖模型直接调用工具,适用于单一场景;MCP通过标准化协议实现模型与工具解耦,支持跨模型、跨设备的动态集成。二者可协同工作,形成“意图解析-协议传输-工具执行”分层架构,未来将趋向融合,推动AI应用生态标准化发展。
|
26天前
|
消息中间件 监控 NoSQL
海量数据下的订单超时取消
本文深入解析海量订单超时取消的分布式调度方案,对比Redis ZSet、延时消息、时间轮等技术优劣,结合大厂实践,提出分层架构与多级延迟策略,兼顾性能、可靠与可扩展性,助力构建高可用订单系统。
104 2
|
26天前
|
运维 自然语言处理 监控
阿里云企业支持计划是什么?企业支持计划服务内容及常见问题解答
阿里云对企业有没有相关的支持或扶持计划?当然是有的,阿里云除基础售后支持外,针对业务系统复杂或对服务有更高要求的客户, 可选择阿里云提供的多种企业支持计划,获取工单极速响应、专属技术保障通道、技术服务经理 (TAM)等专属支持。本文为大家介绍阿里云企业支持计划是什么,介绍其服务内容,并解答一些常见问题。
118 2
lyL
|
26天前
|
存储 NoSQL 关系型数据库
MongoDB相关概念
MongoDB是一款高性能、无模式的文档型数据库,适用于社交、游戏、物流、物联网等大数据量、高并发读写场景。它以BSON格式存储数据,支持灵活的数据模型、丰富查询及水平扩展,尤其适合无需复杂事务、需快速迭代的应用。其高可用、易扩展特性使其成为应对海量数据与高并发需求的理想选择。
lyL
63 1
|
26天前
|
存储 人工智能 数据可视化
阿里云X米兰设计周:用AI创造,助力每一个创作者的想象力落地
阿里云作为第十届米兰设计周中国高校设计展AI技术首席合作伙伴,携手“云工开物”与PAI ArtLab平台,为师生提供专属算力、AIGC工具及学习资源,支持AI创作与模型训练,助力青年学子释放创意潜能,推动AI与设计深度融合。
|
26天前
|
存储 弹性计算 安全
阿里云服务器2核4G收费标准和活动价格参考:u1实例2核4G5M199元,u2a实例504.60元起
现在租用阿里云服务器2核4G配置价格是多少?u1实例2核4G5M带宽有特惠,价格为199元1年,经济型e实例2核4G1M带宽活动价格为599.93元1年起,通用算力型u2a实例2核4G3M带宽的活动价格为648.60元1年,计算型c9a实例2核4G5M带宽活动价格为2938.22元1年起。本文为大家介绍阿里云服务器2核4G配置的实例规格收费标准与最新活动价格情况,以供参考。
134 1
|
26天前
|
XML Java 数据格式
SpringBoot@Configuration
`@Configuration` 注解用于标记配置类,相当于 XML 配置文件。配合 `@Bean` 可注册 Bean 实例,通过注解方式启动 IOC 容器,实现组件的自动加载与管理。

热门文章

最新文章