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

时间:2011-05-04 03:38:23

标签: multithreading erlang kernel coroutine green-threads

  

可能重复:
  Technically why is processes in Erlang more efficient than OS threads?

每次提到Erlang进程或绿线程或协程时,与内核线程相比,它们总是被描述为“轻量级”。通常给出的原因是内核线程涉及上下文切换很慢。

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

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

1 个答案:

答案 0 :(得分:12)

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

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

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

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

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

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