有多less线程创build和什么时候?

我有一个networkingLinux应用程序接收来自多个目的地的RTPstream,做非常简单的数据包修改,然后转发stream到最终的目的地。

如何决定我应该有多less线程来处理数据? 我想,我不能打开每个RTPstream的线程,因为可能有成千上万。 我应该考虑CPU内核的数量吗? 还有什么事呢? 谢谢。

Solutions Collecting From Web of "有多less线程创build和什么时候?"

理解在服务器上使用多个线程的目的是很重要的。 服务器中的许多线程用于减少延迟而不是提高速度。 你不要通过增加线程来让cpu更快,而是让线程更可能在给定的时间段内出现来处理请求。

有一堆线程只是并行移动数据是一个相当低效率的射击枪(每个请求创建一个线程自然是完全失败)。 使用线程池模式可以是一个更有效,更集中的方法来减少延迟。

现在,在线程池中,您希望至少拥有与CPU /内核一样多的线程。 你可以有更多的这个,但额外的线程将再次只减少延迟,而不是增加速度。

把服务器线程组织起来就好像在超级市场上组织线一样。 你想有很多收银员工作得更慢,或者一个收银员工作得更快? 快速收银员的问题不是速度,而是一个有很多杂货的顾客可能仍然占用很多时间。 对许多线程的需求来自这样的可能性:一些请求将花费大量时间并阻塞你所有的线程。 通过这个推理,你是否从很多较慢的收银员中受益取决于你是否拥有相同数量的杂货或数量大不相同的数字。 回到基本的模型,这意味着你必须玩你的线程号码,以根据你的流量的特定特性来计算什么是最优的,看看处理每个请求所花费的时间。

通常,合理线程的数量取决于执行单元的数量,IO与计算的比率以及可用内存。

执行单元数( XU

这就是有多少线程可以同时处于活动状态。 根据您的计算,可能或可能不会计算超线程等内容 – 混合指令工作负载运行得更好。

IO与计算的比率( %IO

如果线程从不等待IO,但总是计算(%IO = 0),则使用比XU多的线程只会增加内存压力和上下文切换的开销。 如果线程总是等待IO并永远不计算(%IO = 1),那么使用poll()select()的变体可能是个好主意。

对于所有其他情况, XU / %IO给出了需要多少线程才能完全使用可用的XU的近似值。

可用内存( Mem

这是更多的上限。 每个线程使用一定量的系统资源( MemUse )。 Mem / MemUse给出了系统可以支持多少个线程的近似值。

其他因素

即使您可以猜测或(更好地)衡量上述数字,整个系统的表现仍然可能受到其他因素的制约。 例如,系统上可能会运行另一个服务,它使用某些XU和内存。 另一个问题是通用可用IO带宽( IOCap )。 如果每个传输字节所需的计算资源少于XU提供的计算资源,那么显然您不需要关心完全使用它们,更多的是关于提高IO吞吐量。

有关后一个问题的更多信息,请参阅Google Talk关于车顶线模型的内容 。

我会说,尝试使用一个线程; 它使编程更容易。 尽管您需要使用诸如libevent之类的东西来复用连接,但不会有任何意外的同步问题。

一旦你有了一个单线程的实现,你可以做性能测试,并决定是否需要多线程。

即使多线程的实现是必要的,但它可能更容易将其分解成多个进程而不是线程(即不共享地址空间;如果它们没有共享地址空间,则可以是fork()或exec多个父进程的副本)大量的共享数据。

你也可以考虑使用类似Python的“Twisted”来简化实现(这是它的设计目的)。

真的,在进程上使用线程可能不是一个好的例子 – 但是也许在你的情况下,很难说。 这取决于您需要在线程之间共享多少数据。

我会看看这个应用程序的线程池。

http://threadpool.sourceforge.net/

允许线程池管理你的线程和队列。

您可以稍后调整基于性能分析的最大和最小线程数。

听听那些建议你使用libevent(或特定于OS的工具,比如epoll / kqueue)的人。 在很多连接的情况下,这绝对是必须的,因为像你所说的那样,创建线程将是一个巨大的性能打击,select()也不能完全切断它。

让你的程序决定。 添加代码来衡量吞吐量,并动态增加/减少线程的数量来最大化它。

这样,无论执行核心的数量和其他因素如何,您的应用程序总是会运行良好

避免尝试为每个客户端请求创建一个(甚至N个)线程是一个好主意。 这种方法通常是不可扩展的,你肯定会遇到内存使用或上下文切换的问题。 你应该看看使用线程池的方法,而将传入的请求作为池中任何线程的任务来处理。 这种方法的可扩展性受到池中理想线程数的限制 – 通常这与CPU内核的数量有关。 你想要让每个线程在单个内核上完全使用100%的CPU,所以在理想情况下,每个内核有1个线程,这将减少上下文切换到零。 根据任务的性质,这可能是不可能的,也许线程不得不等待外部数据,或者从磁盘或其他东西读取,所以你可能会发现线程的数量增加了一些比例因子。