我有一个应用程序(用C语言编写,用于Linux),它必须侦听特定端口上的32个TCP套接字列表。这些套接字可以被用户“屏蔽”,以便在它们被取消屏蔽之前不再为它们报告事件。
我正在使用非阻塞种类的轮询(超时为0),因为我的应用程序没有线程化(不幸的是出于向后兼容性原因)。我的问题是关于在poll数组中有文件描述符的性能影响,它没有事件可以监听(events = 0)而不是动态地延长和缩小数组,这可能是耗时的。
民意调查是否足够聪明,可以“跳过”没有启用任何事件的描述符,或者我会看到它们存在的巨大性能损失?
无论哪种方式,如果套接字将被频繁轮询(可能在100Hz)并且相对不频繁地更改(每秒一次),这两种方法中的哪一种可能会看到最佳性能?没有事件的轮询描述符的开销是否会超过每次我做出更改时必须重新生成数组的开销?
答案 0 :(得分:2)
看kernel code,我会说没有事件描述符的开销很小。我不认为你会发现只有一个描述符的数组和一个只有一个非零事件掩码的32个描述符的数组之间存在任何明显的运行时差异。
拥有更多的描述符确实意味着内核可能需要在内部分配额外的页面来保存结构。所以,如果你有很多丢失的描述符,那么从数组中修剪无事件描述符是有意义的。
操纵数组(struct fds
)绝对不是很耗时。我写了一些测试函数,它们使用两个临时数组 - 一个struct fds
用非零事件掩码填充描述符,送到poll()
,另一个包含指针,以便revents
可以可以轻松更新到原始数组 - 并对它们进行微基准测试。在x86-64(AMD Athlon II X4 640)上,每个描述符的函数大约需要5个时钟周期,在多达一千个描述符的数组上。绝对可忽略的开销,比较甚至基本网络功能消耗的CPU时间!
我担心你会因过早优化而受苦。应用程序或库的整体结构将对实现的效率和速度产生更大的影响。所以,不要担心这一点,花点时间确保你的设计健壮,合理。
我发现尝试确保数据始终保持流动(不阻塞特定接收,尽快读取传入的TCP数据包,尝试在相应数据到达之前进行准备工作,以便数据可以立即被发现,等等,产生相当好的整体结构。
如果您有时间,可以在分析工作应用程序后始终细化细节;从而集中精力应对真正的瓶颈。