epoll

10大高性能开发宝石,我要消灭一半程序员!

為{幸葍}努か 提交于 2020-12-11 12:53:46
这篇文章,我们循序渐进,从内存、磁盘I/O、网络I/O、CPU、缓存、架构、算法等多层次递进,串联起高性能开发十大必须掌握的核心技术。 - I/O优化:零拷贝技术 - I/O优化:多路复用技术 - 线程池技术 - 无锁编程技术 - 进程间通信技术 - RPC && 序列化技术 - 数据库索引技术 - 缓存技术 && 布隆过滤器 - 全文搜索技术 - 负载均衡技术 准备好了吗,坐稳了,发车! 首先,我们从最简单的模型开始。 老板告诉你,开发一个静态web服务器,把磁盘文件(网页、图片)通过网络发出去,怎么做? 你花了两天时间,撸了一个1.0版本: 主线程进入一个循环,等待连接 来一个连接就启动一个工作线程来处理 工作线程中,等待对方请求,然后从磁盘读文件、往套接口发送数据,完事儿 上线一天,老板发现太慢了,大一点的图片加载都有卡顿感。让你优化,这个时候,你需要: I/O优化:零拷贝技术 上面的工作线程,从磁盘读文件、再通过网络发送数据,数据从磁盘到网络,兜兜转转需要拷贝四次,其中CPU亲自搬运都需要两次。 零拷贝技术 ,解放CPU,文件数据直接从内核发送出去,无需再拷贝到应用程序缓冲区,白白浪费资源。 Linux API: ssize_t sendfile( int out_fd, int in_fd, off_t *offset, size_t count );

几种IO模型的原理(实现基于域名PC端和移动端)

烈酒焚心 提交于 2020-12-08 10:13:51
1.服务端IO I/O在计算机中指Input/Output, IOPS (Input/Output Per Second)即每秒的输入输出量(或读写次数),是衡量磁盘性能的主要指标之一。IOPS是指的是在单位时间内系统能处理的I/O请求数量,一般以每秒处理的I/O请求数量为单位,I/O请求通常为读或写数据操作请求。 一次完整的I/O是用户空间的进程数据与内核空间的内核数据的报文的完整交换过程,但是由于内核空间与用户空间是严格隔离的,所以其数据交换过程中不能由用户空间的进程直接调用内核空间的内存数据,而是需要经历一次从内核空间中的内存数据copy到用户空间的进程内存当中,所以简单说一次I/O就是把数据从内核空间中的内存数据复制到用户空间中进程的内存当中的整个过程。 每次IO,都要经由两个阶段: 第一步:将数据从磁盘文件先加载至内核内存空间(缓冲区),此步骤需要等待数据准备完成,时间较长 第二步:将数据从内核缓冲区复制到用户空间的进程的内存中,时间较短 2.系统IO模型 2.1 同步/异步: 同步:进程发出请求调用后,内核不提供通知机制,即文件IO处理完成后不通知进程,需要进程自己去问内核是否处理完成。 异步:进程发出请求调用后,内核会在调用处理完成后返回调用结果给进程,Nginx是异步的。 2.2 阻塞/非阻塞 阻塞:blocking,指IO操作需要彻底完成后才返回到用户空间

实现Linux tail -f功能

我与影子孤独终老i 提交于 2020-12-08 02:15:49
循环 这个比较好像,不停的去读文件,读到就打印出来 f = open( 'a' , 'r' ) print(f.read(),end= '' ) while True : try : print(f.read(),end= '' ) except KeyboardInterrupt: f.close() break CPU占用100%,不是一个好的选择。 select、poll 一直以来,对select和poll的用法局限于套接字,实际上,只要是文件描述符,都可以监控。 select import select f = open( 'a' , 'r' ) while True : try : rs, ws, es = select.select([f, ], [], []) for i in rs: buf = i.read() print(buf, end= '' ) except KeyboardInterrupt: f.close() break poll import select f = open( 'a' , 'r' ) poller = select.poll() fd_to_file = {} poller.register(f,select.POLLIN) while True : try : events = poller.poll() for fd,flag

Muduo网络库源码分析之定时器的实现

南楼画角 提交于 2020-12-07 20:52:37
muduo 的定时器功能由三个 class 实现,TimerId、Timer 和 TimerQueue。 TimerId 类 它唯一标识一个 Timer 定时器。TimerId Class 同时保存Timer* 和 sequence_,这个 sequence_ 是每个 Timer 对象有一个全局递增的序列号 int64_t sequence_,用原子计数器(AtomicInt64)生成。 它主要用于注销定时器,这样就可以区分地址相同的先后两个 Timer 对象。 namespace muduo { namespace net { class Timer; /// /// An opaque identifier, for canceling Timer. /// /* 带有唯一标识的Timer,主要用于取消Timer */ class TimerId : public muduo::copyable { public : TimerId () : timer_ (NULL), sequence_ (0) { } TimerId(Timer* timer, int64_t seq) : timer_(timer), //timer 定时器的指针 sequence_(seq) //seq 该定时任务的序列号 { } // default copy-ctor, dtor and

Muduo网络库源码分析之TcpConnection Class

拟墨画扇 提交于 2020-12-07 20:10:01
用于管理一个具体的 TCP 连接,比如消息的接收与发送,完成用户指定的连接回调 connectionCallback 。 TcpConnection 构造时接收参数有 TCP 连接的 sockfd,服务端地址 localAddr ,客户端地址 peerAddr ,并通过 Socket 封装 sockfd 。并用 Channel 管理该 sockfd,向 Channel 注册可读、可写、关闭、出错回调函数,用于 Poller 返回就绪事件后 Channel::handleEvent() 执行相应事件的回调。 TcpConnection 有四个状态,简单的状态图: TcpConnection 有一系列用户指定的事件回调函数,比如 TcpConnection::connectionCallback 、 messageCallback 、 writeCompleteCallback ,这些是用户通过 TcpServer 传给 TcpConnection。当 Poller 返回 TcpConnection 对应的 Socket 就绪事件时, Channel::handleEvent() -> TcpConnection::handle*系列函数 -> 这些事件回调函数(如 connectionCallback)。 与上面对应,TcpConnection 有一系列 用于 TcpServer

深入浅出TCPIP之实战篇—用c++开发一个http服务器(二十一)

风格不统一 提交于 2020-12-05 16:10:00
专栏其他文章: 理论篇: (一)深入浅出TCPIP之理解TCP报文格式和交互流程 (二)深入浅出TCPIP之再识TCP,理解TCP三次握手(上) (三)深入浅出TCPIP之再识TCP,理解TCP四次挥手(上) (四)深入浅出TCPIP之TCP三次握手和四次挥手(下)的抓包分析 (五)深入浅出TCPIP之TCP流量控制 (六)深入浅出TCPIP之TCP拥塞控制 (七)深入浅出TCPIP之深入浅出TCPIP之TCP重传机制 (八)深入浅出TCPIP之TCP长连接与短连接详解 (九)深入浅出TCPIP之网络同步异步 (十)深入浅出TCPIP之网络阻塞和非阻塞 (十一)深入浅出TCPIP之TCP粘包问题 (十二)深入浅出TCPIP之Nagle算法 (十三) 深入浅出TCPIP之TCP套接字参数 (十四)深入浅出TCPIP之初识UDP理解报文格式和交互流程 (十五)非常全面的TCPIP面试宝典-进入大厂必备总结 (十六)深入浅出TCPIP之Hello CDN .... (二十)深入浅出TCPIP之epoll的一些思考 实践篇: 深入浅出TCPIP之实战篇—用c++开发一个http服务器(二十一) 其他实践篇+游戏开发中的网络问题疑难杂症解读 正在完善。。。 在当前的网络编程专栏前十几篇文章里,我已经说明了TCPIP常用的一些原理,那么接下来我将逐步进入到实战编程阶段: 本篇文章我将带大家用C

(十)深入浅出TCPIP之网络阻塞和非阻塞

不羁的心 提交于 2020-12-05 15:12:34
专栏其他文章: 理论篇: (一)深入浅出TCPIP之理解TCP报文格式和交互流程 (二)深入浅出TCPIP之再识TCP,理解TCP三次握手(上) (三)深入浅出TCPIP之再识TCP,理解TCP四次挥手(上) (四)深入浅出TCPIP之TCP三次握手和四次挥手(下)的抓包分析 (五)深入浅出TCPIP之TCP流量控制 (六)深入浅出TCPIP之TCP拥塞控制 (七)深入浅出TCPIP之深入浅出TCPIP之TCP重传机制 (八)深入浅出TCPIP之TCP长连接与短连接详解 (九)深入浅出TCPIP之网络同步异步 (十)深入浅出TCPIP之网络阻塞和非阻塞 (十一)深入浅出TCPIP之TCP粘包问题 (十二)深入浅出TCPIP之Nagle算法 (十三) 深入浅出TCPIP之TCP套接字参数 (十四)深入浅出TCPIP之初识UDP理解报文格式和交互流程 (十五)非常全面的TCPIP面试宝典-进入大厂必备总结 (十六)深入浅出TCPIP之Hello CDN .... (二十)深入浅出TCPIP之epoll的一些思考 实践篇: 深入浅出TCPIP之实战篇—用c++开发一个http服务器(二十一) 其他实践篇+游戏开发中的网络问题疑难杂症解读 正在完善。。。 阻塞和非阻塞 阻塞和非阻塞 强调的是程序在等待调用结果(消息,返回值)时的状态. 阻塞调用是指调用结果返回之前,当前线程会被挂起

头条后台开发面经

谁说胖子不能爱 提交于 2020-12-05 02:20:31
一面(纯技术面) 队列的实现,需要注意的地方 快速排序的实现、时间复杂度分析 B树和B+树的区别、应用 HashMap的实现,扩容机制,扩容时如何保证可操作 Redis扩容机制(渐进式单线程扩容 ) Spring AOP的原理 Spring IoC的原理,如何实现,如何解决循环依赖 两线程对变量i进行加1操作,结果如何,为什么,怎么解决 CAS概念、原子类实现原理 synchronize底层实现,如何实现Lock AQS有什么特点 可见性的底层原理 JVM内存模型,为什么要这么分 本地方法栈和虚拟机栈的区别 如何查看JVM参数是否正确 TCP三次握手,如何实现 Socket编程底层如何实现 select和epoll的区别 算法:蛇形打印二叉树 二面(项目面+技术面) 项目详聊(问了很多、很细) Innodb多列索引 MySQL默认事务隔离级别,不可重复读是什么意思,如何实现可重复读 Redis服务端有20GB内存,现在要缓存200GB数据,如何处理 算法:给出[[1, 2], [3, 5], [8, 8], [15, 16], [32, 38]],求间隔 什么是堆,画了个二叉树问是否符合最小堆的结构,然后根据图叙述堆排序的详细过程。 TCP与UDP的区别,还有哪些其他的传输层协议,用来做什么的。 进程与线程的区别 ,你是怎么理解这两个概念的(快被问烂了的问题……)

BIO、NIO、AIO 区别和应用场景

你说的曾经没有我的故事 提交于 2020-12-04 19:21:33
点击上方 “ java1234 ”, 选择“ 标星公众号 ” 优质文章,第一时间送达 66套java从入门到精通实战课程分享 简单回顾 对于IO我们应该非常熟悉了,IO不仅仅针对文件的操作,网络编程socket的通信,就是IO操作。 输入、输出流(InputStream、OutputStream)用于读取或写入字节,如操作图片、视频等。 Reader和Writer 则用于操作字符,增加了字符编码功能。本质上计算机操作都是字节,不管是网络或者文件,Reader和Writer等于构建了应用逻辑和原始数据的另一层通道。 BufferedOutputStream、BufferedInputStream等带有缓冲区的实现,可以避免频繁的磁盘操作,通过设计缓冲区将批量数据进行一次操作。 NIO 能解决什么问题? 为什么要有NIO,NIO是什么? 首先看一下BIO,如果有一台服务器,能承受简单的客户端请求,那么使用io和net中的同步、阻塞式API应该是可以实现了。但是为了一个用户的请求而单独启动一个线程,开销应该不小吧。java语言对线程的实现是比较重量的,启动或销毁线程,都会有明显开销,每个线程都有单独的线程棧占用明显的内存。引入线程池,就能很大程度的避免不必要的开销。 这种情况适合连接数并不多,只有最多几百个连接的普通应用,能比较好的进行工作,但如果连接数量剧增

深入解析Linux并发同步

倖福魔咒の 提交于 2020-12-03 11:35:57
并发 是指在某一时间段内能够处理多个任务的能力,而 并行 是指同一时间能够处理多个任务的能力。并发和并行看起来很像,但实际上是有区别的,如下图: 上图的意思是,有两条在排队买咖啡的队列,并发只有一架咖啡机在处理,而并行就有两架的咖啡机在处理。咖啡机的数量越多,并行能力就越强。 linux内核的相关视频: 深度详解Linux内核网络结构及分布 epoll的具体实现与epoll线程安全|互斥锁|自旋锁|原子操作|CAS 手把手带你实现一个Linux内核文件系统 可以把上面的两条队列看成两个进程,并发就是指只有单个CPU在处理,而并行就有两个CPU在处理。为了让两个进程在单核CPU中也能得到执行,一般的做法就是让每个进程交替执行一段时间,比如让每个进程固定执行 100毫秒,执行时间使用完后切换到其他进程执行。而并行就没有这种问题,因为有两个CPU,所以两个进程可以同时执行。如下图: 【文章福利】小编推荐自己的C/C++Linux群:812855908!整理了一些个人觉得比较好的学习书籍、视频资料共享在里面,有需要的可以自行添加哦!~ 原子操作 上面介绍过,并发有可能会打断当前执行的进程,然后替切换成其他进程执行。如果有两个进程同时对一个共享变量 count 进行加一操作,由于C语言的 count++ 操作会被翻译成如下指令: mov eax , [ count ] inc eax mov