究竟是什么让Erlang进程,绿色线程,协程"比内核线程更"轻松?上下文切换怎么样?

Con*_*ion 4 erlang multithreading kernel coroutine green-threads

可能重复:
从技术上讲,为什么Erlang中的进程比OS线程更有效?

无论何时提到Erlang进程或绿线程或协同程序,与内核线程相比,它们总是被描述为"轻量级".通常给出的原因是内核线程涉及缓慢的上下文切换.

但究竟关于上下文切换的速度有多慢呢?与在用户区切换绿色线程相比,它有多慢?

上下文切换是主要(仅?)因素,它解决了事件驱动程序(如Nignx)和多处理程序(如Apache)之间性能和内存消耗的差异?

小智 12

在抢占式,单片式,多任务操作系统上的上下文切换涉及两个路径之一,通过某些系统服务调用(睡眠,互斥锁获取,等待事件,阻塞I/O)或通过中断来调度调度程序.调度程序决定交换正在运行的任务.

当调度程序交换任务时,会发生一些重量级的事情:

  • 所有操作都作为操作系统内核的一部分发生,以高级别权限运行.检查每个操作(或应该是)以确保调度程序做出的决策不会授予任务任何其他权限(请考虑本地root权限)
  • 交换用户模式进程地址空间.这导致内存管理器使用页表布局并将新的目录库加载到控制寄存器中.
  • 这也意味着保存在CPU缓存中的数据可能会被击落并清除.如果您的任务刚刚访问了一堆经常使用的东西,然后上下文切换并"丢失"它(在下一次访问时它[可能]必须再次从主内存中获取),这会很糟糕
  • 根据您进入内核的方式,您需要捕获内核的OUT.例如,如果进行系统调用,CPU将通过一组非常精确的步骤转换为在内核中运行的代码,然后在退出时展开这些步骤.这些步骤比在程序中调用另一个模块的函数更复杂,因此它们需要更多时间.

正如我所理解的那样,绿色线程任务非常简单.用户模式调度程序指示协程运行,直到协程生成.以上几点不同:

  • 协调的调度都不会发生在内核模式中,实际上调度绿色线程通常不需要涉及任何操作系统服务或任何阻塞操作系统服务.所以这一切都可以在没有任何上下文切换或任何用户/内核翻译的情况下发生
  • 绿色线程没有预先安排,甚至根本没有被绿线管理员抢占,它们是合作安排的.这是好的和坏的,但有良好的书面例程,一般都很好.每个任务都完全按照需要执行操作,然后捕获回调度程序,但没有任何上下文交换开销.
  • 绿色线程共享他们的地址空间(据我所知).上下文切换时不会发生地址空间交换.堆栈(据我所知)交换,但这些堆栈由调度程序管理,并且交换堆栈是一个简单的写入寄存器.交换堆栈也是一种非特权操作.

简而言之,用户模式中的上下文切换涉及一些库调用和写入堆栈指针寄存器.内核模式中的上下文切换涉及中断,用户/内核转换以及系统级行为,如地址空间状态更改和缓存刷新.