Event Loop vs Multithread阻塞IO

时间:2021-11-08 00:00:39

I was reading a comment about server architecture.

我正在阅读有关服务器架构的评论。

http://news.ycombinator.com/item?id=520077

In this comment, the person says 3 things:

在这篇评论中,这个人说了三件事:

  1. The event loop, time and again, has been shown to truly shine for a high number of low activity connections.
  2. 事件循环,一次又一次,已被证明真正为大量低活动连接发光。

  3. In comparison, a blocking IO model with threads or processes has been shown, time and again, to cut down latency on a per-request basis compared to an event loop.
  4. 相比之下,与事件循环相比,一次又一次地显示了具有线程或进程的阻塞IO模型,以减少基于每个请求的延迟。

  5. On a lightly loaded system the difference is indistinguishable. Under load, most event loops choose to slow down, most blocking models choose to shed load.
  6. 在轻载系统上,差异无法区分。在负载下,大多数事件循环选择减速,大多数阻塞模型选择减少负载。

Are any of these true?

这些都是真的吗?

And also another article here titled "Why Events Are A Bad Idea (for High-concurrency Servers)"

还有另一篇文章标题为“为什么事件是一个坏主意(对于高并发服务器)”

http://www.usenix.org/events/hotos03/tech/vonbehren.html

2 个解决方案

#1


Typically, if the application is expected to handle million of connections, you can combine multi-threaded paradigm with event-based.

通常,如果应用程序需要处理数百万个连接,则可以将多线程范例与基于事件的连接组合在一起。

  1. First, spawn as N threads where N == number of cores/processors on your machine. Each thread will have a list of asynchronous sockets that it's supposed to handle.
  2. 首先,产生N个线程,其中N ==机器上的核心数/处理器数。每个线程都有一个它应该处理的异步套接字列表。

  3. Then, for each new connection from the acceptor, "load-balance" the new socket to the thread with the fewest socket.
  4. 然后,对于来自接受器的每个新连接,将新套接字“负载平衡”到具有最少套接字的线程。

  5. Within each thread, use event-based model for all the sockets, so that each thread can actually handle multiple sockets "simultaneously."
  6. 在每个线程中,对所有套接字使用基于事件的模型,这样每个线程实际上可以“同时”处理多个套接字。

With this approach,

通过这种方法,

  1. You never spawn a million threads. You just have as many as as your system can handle.
  2. 你永远不会产生一百万个线程。您只需拥有系统可以处理的数量。

  3. You utilize event-based on multicore as opposed to a single core.
  4. 您使用基于事件的多核而不是单核。

#2


Not sure what you mean by "low activity", but I believe the major factor would be how much you actually need to do to handle each request. Assuming a single-threaded event-loop, no other clients would get their requests handled while you handled the current request. If you need to do a lot of stuff to handle each request ("lots" meaning something that takes significant CPU and/or time), and assuming your machine actually is able to multitask efficiently (that taking time does not mean waiting for a shared resource, like a single CPU machine or similar), you would get better performance by multitasking. Multitasking could be a multithreaded blocking model, but it could also be a single-tasking event loop collecting incoming requests, farming them out to a multithreaded worker factory that would handle those in turn (through multitasking) and sending you a response ASAP.

不确定你的“低活动”是什么意思,但我认为主要因素是你实际需要做多少来处理每个请求。假设有单线程事件循环,在处理当前请求时,没有其他客户端会处理其请求。如果你需要做很多事情来处理每个请求(“批量”意味着占用大量CPU和/或时间的东西),并假设你的机器实际上能够有效地进行多任务(花费时间并不意味着等待共享资源,如单个CPU机器或类似机器),您可以通过多任务处理获得更好的性能。多任务处理可以是多线程阻塞模型,但也可以是单任务事件循环,收集传入请求,将它们分配给多线程工作者工厂,这些工厂将依次处理这些工作(通过多任务处理)并尽快向您发送响应。

I don't believe slow connections with the clients matter that much, as I would believe the OS would handle that efficiently outside of your app (assuming you do not block the event-loop for multiple roundtrips with the client that initially initiated the request), but I haven't tested this myself.

我不认为与客户端的缓慢连接非常重要,因为我相信操作系统会在您的应用程序之外有效地处理(假设您没有阻止事件循环与最初发起请求的客户端进行多次往返) ,但我自己没有测试过。

#1


Typically, if the application is expected to handle million of connections, you can combine multi-threaded paradigm with event-based.

通常,如果应用程序需要处理数百万个连接,则可以将多线程范例与基于事件的连接组合在一起。

  1. First, spawn as N threads where N == number of cores/processors on your machine. Each thread will have a list of asynchronous sockets that it's supposed to handle.
  2. 首先,产生N个线程,其中N ==机器上的核心数/处理器数。每个线程都有一个它应该处理的异步套接字列表。

  3. Then, for each new connection from the acceptor, "load-balance" the new socket to the thread with the fewest socket.
  4. 然后,对于来自接受器的每个新连接,将新套接字“负载平衡”到具有最少套接字的线程。

  5. Within each thread, use event-based model for all the sockets, so that each thread can actually handle multiple sockets "simultaneously."
  6. 在每个线程中,对所有套接字使用基于事件的模型,这样每个线程实际上可以“同时”处理多个套接字。

With this approach,

通过这种方法,

  1. You never spawn a million threads. You just have as many as as your system can handle.
  2. 你永远不会产生一百万个线程。您只需拥有系统可以处理的数量。

  3. You utilize event-based on multicore as opposed to a single core.
  4. 您使用基于事件的多核而不是单核。

#2


Not sure what you mean by "low activity", but I believe the major factor would be how much you actually need to do to handle each request. Assuming a single-threaded event-loop, no other clients would get their requests handled while you handled the current request. If you need to do a lot of stuff to handle each request ("lots" meaning something that takes significant CPU and/or time), and assuming your machine actually is able to multitask efficiently (that taking time does not mean waiting for a shared resource, like a single CPU machine or similar), you would get better performance by multitasking. Multitasking could be a multithreaded blocking model, but it could also be a single-tasking event loop collecting incoming requests, farming them out to a multithreaded worker factory that would handle those in turn (through multitasking) and sending you a response ASAP.

不确定你的“低活动”是什么意思,但我认为主要因素是你实际需要做多少来处理每个请求。假设有单线程事件循环,在处理当前请求时,没有其他客户端会处理其请求。如果你需要做很多事情来处理每个请求(“批量”意味着占用大量CPU和/或时间的东西),并假设你的机器实际上能够有效地进行多任务(花费时间并不意味着等待共享资源,如单个CPU机器或类似机器),您可以通过多任务处理获得更好的性能。多任务处理可以是多线程阻塞模型,但也可以是单任务事件循环,收集传入请求,将它们分配给多线程工作者工厂,这些工厂将依次处理这些工作(通过多任务处理)并尽快向您发送响应。

I don't believe slow connections with the clients matter that much, as I would believe the OS would handle that efficiently outside of your app (assuming you do not block the event-loop for multiple roundtrips with the client that initially initiated the request), but I haven't tested this myself.

我不认为与客户端的缓慢连接非常重要,因为我相信操作系统会在您的应用程序之外有效地处理(假设您没有阻止事件循环与最初发起请求的客户端进行多次往返) ,但我自己没有测试过。