Go是否会在处理器密集型操作时阻塞,就像Node一样?

huangapple go评论101阅读模式
英文:

Does Go block on processor intensive operations like Node?

问题

Go非常适合并发编程,任务以go协程的形式传递,并且go协程在虚拟处理器中进行处理。当一个go协程遇到阻塞操作(比如数据库调用)时,该go协程会被移动到另一个虚拟处理器上的不同线程中,而这个线程大部分时间会在另一个物理处理器上运行...现在,我们实现了并行处理。

Node.js也有类似的技术(除了所有操作都在同一个线程上进行),但是它将所有等待的虚拟进程放入等待队列,直到它们从阻塞资源(数据库、URL)接收到响应,然后再进行处理。

Node.js的缺点是它无法处理处理器密集型操作(例如for循环),而且正在执行的虚拟进程会一直占用时间直到完成,没有抢占的机制。这就是为什么在关键系统中使用Node.js时需要谨慎考虑,尽管它具有高并发性能。

是的,Go会生成一个新的线程来处理阻塞的go协程,但是对于处理器密集型操作,它们是否被视为相同情况,或者会遇到Node.js的问题呢?

英文:

Go is great for concurrency, tasks are passed as go-routines, and go-routines are processed in a virtual processor, whenever one go-routine experience a blocking operation (a database call), the go-routine is moved to another virtual processor on a different thread, which is most of the time run on another physical processor ... now, we achieve parallelism.

Node.js has a similar technique (except everything happens on the same thread), but putting all waiting virtual processes in a waiting queue, till they receive responses from the blocking resource (DB, URL), then they are send to be processed.

The down side of Node.js, is its inability to handle processor intensive operations (for loop is an example), and the virtual process being in action, will take all the time till finish without preemption, that's why Node.js is regarded wisely before it's used in critical systems, despite it's high concurrency availability.

Yes, Go spawns a new thread to handle the blocking go-routine, but how about the processor intensive operations, are they regarded the same, or suffer from Node problems?

答案1

得分: 12

是的,但在实践中,与Node相比,它要难以遇到,但恢复起来要容易得多。除非编写显式的多进程代码(这并不总是容易的,特别是如果要实现可移植性),否则Node是单线程的。Go使用N:M调度,具有一定数量的运行线程(默认情况下等于逻辑CPU的数量,但可调整)。注意运行:等待阻塞操作的goroutine被“冻结”,不计入运行线程的占用。

因此,如果有一个单独的goroutine执行CPU密集型任务,通常不会影响其他goroutine的运行能力,因为有一堆其他线程可用于运行它们。如果所有的goroutine都在计算中占用,那么确实其他goroutine在放弃CPU之前将无法运行。如果它们实际上正在完成工作,这可能不一定是个问题,因为所有的CPU都在做实际的工作,但在某些对延迟敏感的情况下可能会有问题。

如果这是个问题,有三个解决方案:

  1. 在长时间计算期间使用runtime.Gosched来放弃对处理器的控制,让其他goroutine有机会运行。不需要进行其他更改;这只是与协作调度器一起工作的一种方式。Gosched可能会立即返回,也可能稍后返回。

  2. 使用工作池来限制并行CPU密集型工作的数量小于GOMAXPROCS。Go使这变得相当容易。

  3. 同样的解决方案的另一面:将GOMAXPROCS提高到预期的并行计算任务数量以上。这可能是最糟糕的想法,会对调度产生一定的影响,但仍然可以工作,并确保有线程可用于处理事件。

英文:

Yes, but it's much more difficult to run into in practice than with Node, and much easier to recover from. Node is single-threaded unless you write explicitly multiprocess code (which isn't always easy, especially if you want to be portable). Go uses N:M scheduling with a certain maximum number of running threads (equal to the number of logical CPUs by default, but tunable). Note running: a goroutine that is waiting for a blocking operation is "frozen" and doesn't count as occupying a running thread.

So, if you have a single goroutine doing something CPU-intensive, it generally won't have an impact on other goroutines' ability to run, because there are a bunch of other threads available to run them. If all of your goroutines are occupied with computation, then it's true that other ones won't get a chance to run until one gives up the CPU. This might not necessarily be a problem if they're actually getting work done, since all of your CPUs are doing actual work, but of course sometimes it can be in latency-sensitive situations.

If it is a problem, three solutions come to mind:

  1. Use runtime.Gosched during long computations to yield control of the processor, allowing other goroutines a chance to run. No other change has to be made; it's just a way of working with the cooperative scheduler. Gosched might return immediately, or it might return later.

  2. Use a worker pool to limit the amount of parallel CPU-intensive work to less than GOMAXPROCS. Go makes this pretty easy.

  3. Flipside of the same coin: raise GOMAXPROCS above the expected number of parallel compute tasks. This is probably the worst of the ideas, and will hurt scheduling at least somewhat, but it will still work, and ensure you have threads available for handling events.

答案2

得分: 1

Go使用协作式多任务处理。一个不执行任何让出控制权给Go调度器的goroutine可以垄断一个线程。

英文:

Go uses cooperative multitasking. A goroutine that doesn't do anything that cedes control to the Go scheduler, can monopolize a thread.

huangapple
  • 本文由 发表于 2016年2月18日 10:07:56
  • 转载请务必保留本文链接:https://go.coder-hub.com/35471480.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定