在我的应用程序中,我开始在多个位置使用
select()
调用,监视进程中的不同事物(网络连接、IPC、消息传递、文件...)。
所有调用都使用其自己的文件描述符集,这意味着在选择中不会使用两次描述符。
这意味着有时候,我有类似 5 个
select()
调用在不同的线程中阻塞。
在不同线程中多次使用
select()
是否会造成性能损失,而不是仅使用 one 调用并将结果分派到相应的线程?
实际上,一次待处理的
select()
呼叫数量有限制吗?
有没有工具可以测量这个?
由于应用程序可能会变得更大,我怀疑在某些时候,如果这开始出现问题,我将不得不编写某种集中式
select()
,它会收集所有 FD 进行监视,并在数据出现时通知客户端线程已准备好收集/编写。
所以我想我最好先问一下...
您不太可能注意到任何性能差异。
在内核内部,
select
将您的线程添加到您选择的每个描述符的“等待队列”中,并将其置于睡眠状态。如果您选择 n
描述符,您的线程将被添加到 n
等待队列中。当描述符发生可轮询的情况时(例如,数据到达套接字),该等待队列上的所有线程都会被唤醒。
选择大量描述符会将您添加到大量等待队列中。一旦唤醒,您的线程将必须从所有这些等待队列中删除,包括那些没有活动的线程。因此,在这一方面,在多个线程中等待一小部分描述符而不是在一个线程中等待一大堆描述符可能会有一些轻微的好处。
另一方面,
select
本身要求内核循环遍历所有可能的描述符以查看哪些是您的fd_set
的成员。因此,在这一方面,只有一个线程进行 select
调用可能会有一些轻微的优势...
总的来说,我猜这是一次洗涤。
如果您要处理大量描述符,那么最好使用更具可扩展性(尽管不可移植)的机制,例如
epoll
。使用 epoll
,每个处理描述符池的多个线程应该可以很好地扩展。
select 调用应该在操作系统中处理,正如您所说 - 它是阻塞的,而不是轮询 - 因此它不会对您的应用程序造成性能损失。我也不认为除了对操作系统一般可以打开的文件描述符数量有任何限制之外,使用它不会有任何限制,这与 select 无关。