协程的设计原理(一)

简介: 协程的设计原理(一)

1 解决问题

目前主流的协程libgo(golang提供);libco(腾讯开源),libgo使用起来方便,自己的工程也是采用libgo实现的全球同服的服务器框架。解决了采用同步的方式实现异步的性能。

2 同步/异步/协程关系

1 同步与异步区别

对于同步来说是,业务服务器发送一个请求后,等待第三方服务器返回后继续执行其它操作;异步是不需要等待返回,直接执行其它操作,当第三方服务器返回时候,在通过回调方式来通知业务服务器对应响应的处理。

异步的实现方式可以看前面的博客(异步请求池实现)四元组.

2 具体编程实现

不采用线程池和采用线程池的对比

//不采用线程池的大体逻辑
while(1){
  int nready = epoll_wait(); // 检测io
  for(i = 0; i < nready; i++){
    recv();   // 对io操作
      parese(); // 解析buffer
    send();
  }
}
// 加入线程池大体逻辑
void mainloop(){  // 主线程
  while(1){
    int nready = epoll_wait(); 
    for(i = 0; i < nready; i++){
      /*recv(buffer);
        parese();
      send();
      */
      push_to_workqueue(work_cb); // 抛入线程池
    }
  }
}
// 另外一个子线程
void *work_cb(void *arg){
  recv(buffer);
    parese();
  send(buff);
}

注意加线程池的性能大概提升不加线程池的3倍左右。

对于服务器来说,当检查io和读写io是在同一个流程里就叫同步;而不在同一个流程(例如添加线程池后)就叫异步

区别:

同步实现简单,流程清晰符合人的思维方式,效率相对来说不高;

异步实现复杂,效率相对来说较高。

为了中和同步和异步,需要采用同步的方式实现异步的性能,两者优点都想要所以产生了协程.

3 异步和协程的关系

异步实现主要是在commit和callback两个部分。具体流程如下

对于协程来讲,在fd添加到epoll管理后,引入一个yield()原语操作让出操作,去执行其它的就绪的,在resume()恢复到现场,继续往下执行。

3 yield()和resume()原语实现方案

常见的实现方案:

a) setjmp/longjmp

b) ucontext(linux底层提供的)

c) 汇编代码实现跳转

对于第一种setjmp/longjmp实现起来比较简单在对应的位置调用api即可。

而汇编代码实现可读行更强,推荐采用第三种方式汇编实现(大部分情况下是直接用开源组件来调用即可)

两者底层都调用switch接口。

4) 协程切换

对于原语yield和resume操作底层都是通过switch(A,B)实现。以单cpu为例:来看协程切换流程:

协程A让出给B,将cpu寄存器值保存到协程A中(定义一组结构体struct context);
当切换的时候,加载协程B的数据到cpu寄存器中。
)

5) 协程创建

协程框架会提供一个接口用于创建协程,创建完成的协程添加到就绪队列,协程的入口函数通过寄存器eip将协程函数保存起来。

6) 协程的定义

协程包括:就是要封装一个协程的结构体。

context上下文,stack栈空间,协程栈大小,协程入口函数,入口参数,协程的状态集合(wait,sleep,ready),exit,status状态

状态集合:wait状态采用红黑树或者队列实现,sleep休眠可采用红黑树和最小堆实现,ready状态可采用队列实现

目录
相关文章
|
6月前
|
API 调度
2.3.1 协程设计原理与汇编实现
2.3.1 协程设计原理与汇编实现
|
3月前
|
存储 Linux 调度
协程(coroutine)的原理和使用
协程(coroutine)的原理和使用
|
12天前
|
存储 安全 测试技术
GoLang协程Goroutiney原理与GMP模型详解
本文详细介绍了Go语言中的Goroutine及其背后的GMP模型。Goroutine是Go语言中的一种轻量级线程,由Go运行时管理,支持高效的并发编程。文章讲解了Goroutine的创建、调度、上下文切换和栈管理等核心机制,并通过示例代码展示了如何使用Goroutine。GMP模型(Goroutine、Processor、Machine)是Go运行时调度Goroutine的基础,通过合理的调度策略,实现了高并发和高性能的程序执行。
74 29
|
10天前
|
负载均衡 算法 Go
GoLang协程Goroutiney原理与GMP模型详解
【11月更文挑战第4天】Goroutine 是 Go 语言中的轻量级线程,由 Go 运行时管理,创建和销毁开销小,适合高并发场景。其调度采用非抢占式和协作式多任务处理结合的方式。GMP 模型包括 G(Goroutine)、M(系统线程)和 P(逻辑处理器),通过工作窃取算法实现负载均衡,确保高效利用系统资源。
|
2月前
|
调度 Python
揭秘Python并发编程核心:深入理解协程与异步函数的工作原理
在Python异步编程领域,协程与异步函数成为处理并发任务的关键工具。协程(微线程)比操作系统线程更轻量级,通过`async def`定义并在遇到`await`表达式时暂停执行。异步函数利用`await`实现任务间的切换。事件循环作为异步编程的核心,负责调度任务;`asyncio`库提供了事件循环的管理。Future对象则优雅地处理异步结果。掌握这些概念,可使代码更高效、简洁且易于维护。
24 1
|
1月前
|
数据采集 调度 Python
Python编程异步爬虫——协程的基本原理(一)
Python编程异步爬虫——协程的基本原理(一)
|
1月前
|
数据采集 Python
Python编程异步爬虫——协程的基本原理(二)
Python编程异步爬虫——协程的基本原理(二)
|
1月前
|
存储 前端开发 rax
协程设计与原理(二)
协程设计与原理(二)
15 0
|
4月前
|
调度 Python
揭秘Python并发编程核心:深入理解协程与异步函数的工作原理
【7月更文挑战第15天】Python异步编程借助协程和async/await提升并发性能,减少资源消耗。协程(async def)轻量级、用户态,便于控制。事件循环,如`asyncio.get_event_loop()`,调度任务执行。异步函数内的await关键词用于协程间切换。回调和Future对象简化异步结果处理。理解这些概念能写出高效、易维护的异步代码。
58 2
|
6月前
|
存储 关系型数据库 MySQL
纯c协程框架NtyCo实现与原理
纯c协程框架NtyCo实现与原理
148 1