代码中有一条快速路径,如下所示:
while(1){
select(fd_set...);
if (fd_isUserspace) {
process_user_packet(fd); // RPC involved
} else { // kernel
process_kernel_packet(fd); // RPC invovled
}
} // while(1)
基本上从一组fds读取一个活动的fd并处理它。目前,它在if-else分支中完成,仅在处理完成时返回。我想我可以通过在if-else中使用线程池(poolSize> = 2)来改进这一点,以便处理函数立即返回并且可以为将来的fds再次开始while循环。
大概是进程_ * _数据包会做一些RPC处理工作。
我知道将处理作业分配给一个线程可能会有一些开销(thread_cond_signal / locking等),但感觉因为进程_ * _数据包可能需要时间更大(由于RPC)这是值得的。
想得到一些想法(可能更好的想法),我认为这可能是一个非常笼统的问题,关于如何设计以获得更好的性能。
-Thanks
答案 0 :(得分:2)
我最近用Java编写了一个线程池(我的并行计算类是必需的,我知道它是内置的),如果你正确编写它,它实际上非常快。
如果您使用多个线程,这里有一个巨大的优势:您不再需要阻止请求。您将获得更好的响应时间,因为您可以同时处理多个请求。
如果需要花费相当长的时间来处理,发送或接收,那么您不需要该数据包就必须堵塞管道。
使用一些线程池,您只需:
while(1){
select(fd_set...);
if (fd_isUserspace) {
submit_job(process_user_packet, fd);
} else { // kernel
submit_job(process_kernel_packet, fd);
}
} // while(1)
我们假设submit_job有签名
void submit_job(void (*func)(void *), void *args);
这样线程池中的每个线程都可以简单地获取它需要处理的函数和参数,并调用func(args);
我根本不担心调度工作的成本。如果处理时间超过1毫秒(在真正好的实现上可能更少),那么你将是金色的。
答案 1 :(得分:1)
只是一个想法,但是如果你丢弃select
并且每个文件描述符只使用一个线程呢?如果同时出现太多请求,唯一的主要缺点是上下文切换开销,但这可能比延迟更好。优点是在非重载情况下更少的上下文切换:内核在解除阻塞后立即直接唤醒等待文件描述符的线程,而不是首先唤醒选择线程,然后必须唤醒线程以处理请求。当然还有一些优势的简单性......