Multithreading 究竟是什么让Erlang进程、绿色线程、协同路由“成为现实;“打火机”;而不是内核线程?那么上下文切换呢';它重吗?

Multithreading 究竟是什么让Erlang进程、绿色线程、协同路由“成为现实;“打火机”;而不是内核线程?那么上下文切换呢';它重吗?,multithreading,erlang,kernel,coroutine,green-threads,Multithreading,Erlang,Kernel,Coroutine,Green Threads,可能重复: 每当提到Erlang进程、绿色线程或协同路由时,与内核线程相比,它们总是被描述为“轻量级”。通常给出的原因是内核线程涉及到上下文切换,这很慢 但是,对于缓慢的上下文切换,又该怎么办呢?与在userland中切换绿色线程相比,它要慢多少 上下文切换是导致事件驱动程序(如Nignx)和多处理程序(如Apache)在性能和内存消耗方面存在差异的主要(唯一)因素吗?在抢占式、单片式、多任务操作系统上进行上下文切换涉及两种途径之一,通过某些系统服务调用(睡眠、互斥获取、等待事件、阻塞I/O)

可能重复:

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

但是,对于缓慢的上下文切换,又该怎么办呢?与在userland中切换绿色线程相比,它要慢多少


上下文切换是导致事件驱动程序(如Nignx)和多处理程序(如Apache)在性能和内存消耗方面存在差异的主要(唯一)因素吗?

在抢占式、单片式、多任务操作系统上进行上下文切换涉及两种途径之一,通过某些系统服务调用(睡眠、互斥获取、等待事件、阻塞I/O)或通过中断和调度器决定交换正在运行的任务,向调度器暗示让步

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

  • 所有操作都作为操作系统内核的一部分,以高权限运行。检查(或应该检查)每个操作,以确保调度程序所做的决定不会授予任务任何附加权限(考虑本地根攻击)
  • 交换用户模式进程地址空间。这导致内存管理器处理页表布局,并将新的目录基加载到控制寄存器中
  • 这也意味着保存在CPU缓存中的数据可以被删除和清除。如果您的任务刚刚访问了一堆常用的东西,然后上下文切换并“丢失”了它,那么这将很糟糕(下次访问时,它[可能]必须再次从主内存中提取)
  • 取决于您捕获内核的方式,然后需要捕获内核。例如,如果进行系统调用,CPU将经历一组非常精确的步骤,以转换到内核中运行的代码,然后在退出时释放这些步骤。这些步骤比对程序中的另一个模块进行函数调用要复杂得多,因此它们需要更多的时间
据我所知,绿色线程任务非常简单。用户模式调度器指示协同路由运行,直到协同路由产生。以上几点不同:

  • 协同路由的调度都不是在内核模式下进行的,实际上,调度绿色线程通常不需要涉及任何操作系统服务或任何阻塞的操作系统服务。因此,所有这些都可以在没有任何上下文切换或任何用户/内核转换的情况下实现
  • 绿色线程不是抢占调度的,甚至根本不是由绿色线程管理器抢占的,它们是协作调度的。这是好是坏,但对于编写良好的例程,通常是好的。每个任务都精确地执行它需要执行的操作,然后将其捕获回调度程序,但没有任何上下文交换开销
  • 绿色线程共享它们的地址空间(据我所知)。上下文开关上不会发生地址空间的交换。堆栈是(据我所知)交换的,但这些堆栈由调度程序管理,而且交换堆栈只需简单地写入寄存器。交换堆栈也是一种非特权操作

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

+1对于一个写得好的问题,即使是重复的。在合理的体系结构(具有物理寻址缓存的体系结构)上,缓存通常不会在上下文开关上清除。Erlang进程确实使用抢占式调度。Erlang VM管理上下文切换。这一点非常重要,因为长时间运行的进程不能以这种方式阻止其他进程。这是一个Erlang特性。Erlang还对每个进程进行垃圾收集,而且Erlang进程很小。所有这些都使Erlang成为实时系统的合适语言。@caf:虽然缓存确实没有立即清除,但它将在切换线程的进一步工作中被逐出。有研究表明,线程间上下文切换的缓存失效成本可能高达100万个CPU周期。@Jonas那么你能回答Erlang的问题吗?为什么Erlang线程比OS线程更轻?