前言

学习自用,还有很多不足的地方

异步IO和同步IO

当网卡有了数据,DMA会把数据拷贝到内核缓冲区(内核缓冲区的哪里呢);而从内核缓冲区拷贝到用户态需要用户调用read,同步地进行

异步则是注册个读完成事件,等其他用户态线程/内核进程拷贝到用户态后再提醒

aio最核心的需求就是解偶submit和wait for completion, 简单地说就是在submit的时候不要阻塞, 这样用户在submit之后可以做其它事情或者继续submit新的io, 从而获得更高的cpu利用率和磁盘带宽.

异步IO的好处

  1. 同步read从内核区拷贝到用户态需要等待短暂的时间,全异步的aio_read不存在这个短暂时间(同步read的系统调用和从内核拷贝到用户的时间),效率更高;异步IO一个例子就是nginx的读文件的操作(?)
  2. 那在内核上处理的真正异步io的优势在于:和同步非阻塞io相比,优势主要在于不用维护数据读不齐时的逻辑处理(可能是等到读齐了再通知吧)

异步IO的坏处

  1. 要提前规定好缓冲区大小以在数据到来时自动拷贝,如果设置太大会浪费,太小又有问题,而同步IO可以在读取时适时增加和释放空间,比如muduo就在read的同时用writev增加栈上buffer大小
  2. 另外异步IO的编程会麻烦一点,调用aio_read后还要有等待完成读取的逻辑,看看nginx里面文件操作就知道用起来多痛苦了(不过应该可以优化,用promise/future或await来优化?..那实现得更麻烦了)

Linux的AIO

  1. POSIX的AIO(应该就是glic的aio),是用pthread实现的用回调或signal通知的,没有connect,accept等网络IO的API
  2. kernel 的 aio,即kernel native AIO,被用在了nginx上,有一个封装libaio,一开始是为了数据库涉及的,所以只能以 O_DIRECT 方式做直接 IO,即跳过page cache直接写入磁盘(数据库应用这种实现如INNODB,它在应用层实现自己的cache机制而不用OS的page cache),这就导致一些问题如data buffer的对齐,它要求读写的的大小和偏移要以区块的方式对齐即offset与size的对齐(都是啥啊?),估计普通用户不会愿意触及这个。除了数据库的开发者。而且网络API一样没有。另外kernel native AIO存在额外的开销,每个IO提交需要拷贝64+8字节,每个IO完成需要拷贝32字节,这在某些场景下影响很可观。在使用完成event的时候需要非常小心,否则容易丢事件。IO总是需要至少2个系统调用(submit + wait-for-completion),在spectre/meltdown开启下性能下降非常严重。
  3. 还有一个libev作者搞的libeio,在beta阶段,设计上汲取了前两个的经验用了一些tricky的办法,也是用线程在用户态模拟的,bug更少但是代码更难看懂。封装了大量的文件API ,但也没有网络API。而且有bug的,不能用在 socket 读写上,而且不会返回显式错误,而是自动切成非异步 IO
  4. 最新内核引入的io_uring可能可以统一网络和磁盘的aio模式。

AIO实现

AIO复制数据从内核态到用户态的时候,可能会发生一些问题阻塞住,如申请用户态的空间不够,请求队列slot和inode的semaphore(是啥?)

用何种方式来提醒读写完成呢,

  • 信号IO不仅在大量IO操作时可能会因为信号队列溢出导致没法通知(?)
  • 定义一个回调函数,用sigfd也可以,则需要用eventloop来进行监听,复杂的话可以用promise/future来简化语法
  • Filesystem/Buffered AIO: Buffered IO与Direct IO的资源冲突和数据完整问题(??)

内核线程来或者单独用一个线程进行read操作,(用多线程会有多个读一个fd的问题),要维护read的队列,传入读出来存的地方

猜想

猜想:如果大量不断的连接到来事件然后断开...

listen socket的可读事件,消息socket可读事件,如果让其中一个单独用一个线程异步处理,则开销是:逻辑复杂度,另外的线程开销,活跃线程多的情况会有切换开销,好处是IO线程不需要用到系统调用read,IO线程阻塞时间变少

猜想:如果大量不断到来然后发送一小段东西然后断开...

同理上面吧,这样的场景更适合异步,因为read时间更长,不过如果一直是消息到来事件,瓶颈就在CPU上,那个异步线程毕竟也是单核处理,如果夹杂着其他不耗时事件到来,这些事件响应可能会变高

异步更高效的场景

IO线程做的事:epoll_wait->分发事件;

如果是大量socket的大量数据且到来,则read耗时长,总结下两个缺点:

  1. 同步read会阻塞epoll_wait的调用,也就延迟了socket的处理,假如同时夹杂着不耗时的socket连接到来事件则客户端响应会变慢;只能通过每个只读少量大小的方式来保证socket的及时处理,但这样不管是LT或ET+robin list都会增加额外系统调用开销或应用复杂度;
  2. read操作从内核搬数据到用户态无法利用多核,实现得好的话,可以让多个异步来处理异步IO(多个异步线程这样实现应该会难吧,还会有跨线程读同一个fd的问题,如果用epoll_oneshot来解决还会有epoll_ctl系统调用的性能损耗);单核CPU当然是同步更高效;

综上:多核下的大量socket的大量数据(夹杂着大量耗时少的事件如连接到来事件应该更明显),应该是异步IO的QPS更高(连接到来的socket和大量数据的socket事件响应,应不应该分开来算啊?)

同步更高效的场景

单核情况下,用异步会多一次上下文切换和一些多出来的步骤

TODO

  1. 为什么linux难以实现异步IO,写完了还不是很懂
  2. 光明说的,AIO有多个线程操作,第一次事件用AIO_read,但是没被及时处理,因为LT,所以下次再出发再调用aio_read,线程不同了会有问题吧,也就是多线程处理epoll事件的问题,epoll还提供了oneshot这个标志位?...又说好像问题不大,不过和其他场景可能有问题,就是跟oneshot的问题是一样的

参考资料

  1. Linux上没有真正的异步,为什么服务器还是用Linux的多? - 知乎 https://www.zhihu.com/question/41706901
  2. linux下的异步IO(AIO)是否已成熟? - 知乎 https://www.zhihu.com/question/26943558
  3. 如何深刻地理解 Unix/Linux 中同步 IO 和异步 IO? - 知乎 https://www.zhihu.com/question/352921402
  4. 为什么Linux下没有真正的异步IO模型? - 知乎 https://www.zhihu.com/question/421584363
  5. 吐槽linux,AIO的https://www.aikaiyuan.com/4556.html有点复杂,看不太懂
  6. https://kernel.taobao.org/2019/06/io_uring-a-new-linux-asynchronous-io-API/最新的io_uring
  7. https://zhuanlan.zhihu.com/p/149836046一开始linux AIO的设计出发点和io_uring,有点复杂比如阻塞点
  8. understanding linux kernel的6.2章节

异步IO实现和应用场景相关推荐

  1. 五种I/O 模式——阻塞(默认IO模式),非阻塞(常用语管道),I/O多路复用(IO多路复用的应用场景),信号I/O,异步I/O

    From: http://blog.163.com/xychenbaihu@yeah/blog/static/13222965520112163171778/ 五种I/O 模式: [1]        ...

  2. Node的异步与java的异步_node中异步IO的理解

    解释性语言和编译型语言的区别: 计算器不能直接的理解高级语言,只能理解机器语言,所以必须把高级语言翻译为机器语言,翻译的方式有两种,一个是编译,一个是解释. 解释性语言的程序不需要编译,它是在运行程序 ...

  3. 异步IO一定更好吗?

    http://cnodejs.org/blog/?p=1015 续:异步IO一定更好吗? 我之前的一篇文章<异步IO一定更好吗?>中举了一个很变态的例子,用以说明在单碟机械式硬盘上异步IO ...

  4. Node - 异步IO和事件循环

    前言 学习Node就绕不开异步IO, 异步IO又与事件循环息息相关, 而关于这一块一直没有仔细去了解整理过, 刚好最近在做项目的时候, 有了一些思考就记录了下来, 希望能尽量将这一块的知识整理清楚, ...

  5. linux AIO (异步IO) 那点事儿

    在高性能的服务器编程中,IO 模型理所当然的是重中之重,需要谨慎选型.对于网络套接字,我们可以采用epoll 的方式来轮询,尽管epoll也有一些缺陷,但总体来说还是很高效的,尤其来大量套接字的场景下 ...

  6. python异步io多文件_Python 异步 IO 性能又上一层楼

    最近看源码的过程中,发现了一个比较有意思的库,aiomultiprocess,我认为他确实是 Python 升级到 3.8 之后一个特性的总结库,包括静态检查和性能提升. 这个是作者提供的一个 IO ...

  7. java epoll select_Java 非阻塞 IO 和异步 IO

    点击上方 Java后端,选择 设为星标 优质文章,及时送达 作者 | HongJie 链接 | javadoop.com/post/nio-and-aio 本文将介绍非阻塞 IO 和异步 IO,也就是 ...

  8. Thrift异步IO服务器源码分析

    http://yanyiwu.com/work/2014/12/06/thrift-tnonblockingserver-analysis.html 最近在使用 libevent 开发项目,想起之前写 ...

  9. node中异步IO的理解

    解释性语言和编译型语言的区别: 计算器不能直接的理解高级语言,只能理解机器语言,所以必须把高级语言翻译为机器语言,翻译的方式有两种,一个是编译,一个是解释. 解释性语言的程序不需要编译,它是在运行程序 ...

  10. 操作系统与存储:解析Linux内核全新异步IO引擎io_uring设计与实现

    作者:draculaqian,腾讯后台开发工程师 引言 存储场景中,我们对性能的要求非常高.在存储引擎底层的IO技术选型时,可能会有如下讨论关于IO的讨论. http://davmac.org/dav ...

最新文章

  1. 最新必读图神经网络论文
  2. Grails下 Membership和全文搜索实战录
  3. yii2手册_史上最全的技术手册整理总结,编程小白都从这篇文章迅速成为大牛...
  4. 对象化下的编程——字段
  5. 用了2年多快3年的老ASUS本子出了点小问题了
  6. Product Overview page data loss handling
  7. Codeforces686C【dfs】
  8. 学习笔记(01):5天Python闯关训练营-103期-re模块使用案例
  9. Windows UWF 实现系统重启还原(2021.11.02)
  10. c语言输出最大的数ns流程图_怎么将100至200中全部的素数用NS流程 – 手机爱问...
  11. 搜索引擎的查找算法实现
  12. 转移操作和占用操作主机
  13. 一文读大厂微服务水平
  14. 将手机流氓软件彻底赶出去
  15. rap格式鸿蒙,你,想要成为rap star吗?
  16. STM32 学习笔记 expected a type specifier
  17. # 前端初学html+css+js+bootstrap4+jquery部分后的简单响应式静态网页编写(漫威主题个人博客)
  18. TCP/IP协议连接状态详解
  19. Linux 系统调用深思:从原理到实战
  20. [ 7天学习Python编程,第一天]-----1.4 Python main函数:了解__main__【python舵手】

热门文章

  1. 推荐一款windows下好用的文件夹加密、文件加密软件(含使用说明)
  2. java dcm4che findscu实现workList通讯——客户端SCU
  3. 迅为IMX6ULL开发板Linux下电容触摸屏实验-实验程序编写
  4. 纹理——灰度共生矩阵公式及代码
  5. error500java_错误 500 java.lang.NoClassDefFoundError: com/lowagie/text/pdf/FontMapper
  6. 计算机教室电脑无法启动,电子教室教师端不能启动没开机的学生机的解决办法...
  7. ucinet计算聚类系数大于1怎么办_ucinet使用说明技巧.ppt
  8. PMP备考资料和备考经验分享(基于PMP第六版)
  9. 导师如何“温柔”地督促参加学术活动的研究生
  10. win10任务栏透明_谈谈我的Windows系统使用历程和win10桌面美化