我正在写一个服务器,当收到请求时,我将每个动作发送到一个单独的线程。我这样做是因为几乎每个请求都要进行数据库查询。我正在使用线程池库来减少线程的构造/破坏。
我的问题是:对于这样的I/O线程,什么是一个好的截断点?我知道这只是一个粗略的估计,但我们说的是几百吗?成千上万的吗?
我怎么才能算出这个界限呢?
编辑:
感谢大家的回复,似乎我只是要测试一下,以找出我的线程数上限。问题是:我怎么知道我已经达到上限了呢?我到底应该测量什么?
我正在写一个服务器,当收到请求时,我将每个动作发送到一个单独的线程。我这样做是因为几乎每个请求都要进行数据库查询。我正在使用线程池库来减少线程的构造/破坏。
我的问题是:对于这样的I/O线程,什么是一个好的截断点?我知道这只是一个粗略的估计,但我们说的是几百吗?成千上万的吗?
我怎么才能算出这个界限呢?
编辑:
感谢大家的回复,似乎我只是要测试一下,以找出我的线程数上限。问题是:我怎么知道我已经达到上限了呢?我到底应该测量什么?
当前回答
我认为这有点回避你的问题,但是为什么不把它们分成进程呢?我对网络的理解(从以前模糊的日子里,我根本就没有编写网络代码)是每个传入的连接都可以作为一个单独的进程来处理,因为如果有人在您的进程中做了一些讨厌的事情,它不会破坏整个程序。
其他回答
如果您的线程正在执行任何类型的资源密集型工作(CPU/磁盘),那么您很少会看到超过一到两个的好处,太多会很快降低性能。
“最好的情况”是,当第一个线程完成时,后面的线程将会停止,或者一些线程在资源上有低开销的块,且资源争用低。最坏的情况是您开始折腾缓存/磁盘/网络,并且您的总体吞吐量下降到地板。
一个好的解决方案是将请求放在一个池中,然后从线程池分派给工作线程(是的,避免持续的线程创建/销毁是很好的第一步)。
然后,可以根据概要分析的结果、正在运行的硬件以及机器上可能发生的其他情况调整和缩放此池中的活动线程数。
和CPU内核一样多的线程是我经常听到的。
这个问题已经讨论得很透彻了,我还没有机会阅读所有的回答。但是,在查看可以在给定系统中和平共存的并发线程数量的上限时,有几件事需要考虑。
Thread Stack Size : In Linux the default thread stack size is 8MB (you can use ulimit -a to find it out). Max Virtual memory that a given OS variant supports. Linux Kernel 2.4 supports a memory address space of 2 GB. with Kernel 2.6 , I a bit bigger (3GB ) [1] shows the calculations for the max number of threads per given Max VM Supported. For 2.4 it turns out to be about 255 threads. for 2.6 the number is a bit larger. What kindda kernel scheduler you have . Comparing Linux 2.4 kernel scheduler with 2.6 , the later gives you a O(1) scheduling with no dependence upon number of tasks existing in a system while first one is more of a O(n). So also the SMP Capabilities of the kernel schedule also play a good role in max number of sustainable threads in a system.
现在,您可以调整堆栈大小以合并更多线程,但随后必须考虑线程管理的开销(创建/销毁和调度)。 您可以对给定进程和给定线程强制CPU Affinity,将它们绑定到特定的CPU上,以避免CPU之间的线程迁移开销,并避免冷现金问题。
请注意,一个人可以根据自己的意愿创建数千个线程,但是当Linux耗尽VM时,它只是随机地开始杀死进程(因此线程)。这是为了防止实用程序配置文件被刷爆。(效用函数表示给定资源数量的系统范围效用。在这种情况下,CPU周期和内存的资源不变,效用曲线会随着任务数量的增加而变平)。
我相信windows内核调度器也会做一些这样的事情来处理资源的过度使用
[1] http://adywicaksono.wordpress.com/2007/07/10/i-can-not-create-more-than-255-threads-on-linux-what-is-the-solutions/
在大多数情况下,您应该允许线程池处理这个问题。如果您发布一些代码或提供更多细节,可能更容易看到是否有某些原因导致线程池的默认行为不是最好的。
你可以在这里找到更多关于如何工作的信息:http://en.wikipedia.org/wiki/Thread_pool_pattern
你应该记住的一件事是,python(至少是基于C的版本)使用了所谓的全局解释器锁,它可以对多核机器的性能产生巨大影响。
如果你真的很需要多线程python,你可能会考虑使用Jython或其他东西。