Linux轮询()1 fd写入后很慢,读取后很快

问题

我正在观察poll()调用在write()操作之后立即调用时会花费毫秒,而在read()操作之后立即调用时仅需要几微秒。

这是使用ACE C ++通信库的代码。

我试图理解为什么在调用write()之后调用poll()所花费的系统CPU时间与read()调用相比存在显着差异。

系统

  [root @ host〜 ] #lsb_release -a
 LSB版本:: core-4.0-amd64:core-4.0-ia32:core-4.0-noarch:graphics-4.0-amd64:graphics-4.0-ia32:graphics-4.0-noarch:printing-4.0-amd64:printing-4.0- IA32:印刷-4.0-noarch
分销商ID:RedHatEnterpriseServer
说明:红帽企业Linux服务器版本5.9(Tikanga)
发布:5.9
代号:Tikanga 

strace的

 (234,“\ 4 \ 0S \ 0 \ 0 \ 0 \ 0 \ 0 \ 1 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 3 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0“...,256)= 256 <0.000048>
 poll([{fd = 234,events = POLLIN}],1,-1)= 1([{fd = 234,revents = POLLIN}])< 0.006 036>
读取(234,“\ 4 \ 0S \ 0 \ 0 \ 0 \ 0 \ 0 \ 1 \ 0 \ 0 \ 0
 (234,“\ 4 \ 0S \ 0 \ 0 \ 0 \ 0 \ 0 \ 1 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 3 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0“...,256)= 256 <0.000192>
 poll([{fd = 234,events = POLLIN}],1,-1)= 1([{fd = 234,revents = POLLIN}])< 0.004 996>
 (234,“\ 4 \ 20S \ 0 \ 0 \ 0 \ 0 \ 0 \ 1 \ 0 \ 0 \ 0 \ 200 \ 2 \ 0 \ 0 \ 0 \ 0 \ 3 \ 0 \ 1 \ 0 \ 0 \ 10 \ 1 \ 0 \ 200 \ 2 \ 0 \ 0“...,256)= 256 <0.000076>
 poll([{fd = 234,events = POLLIN}],1,-1)= 1([{fd = 234,revents = POLLIN}])<0.000022>
 (234,“\ 2 \ 0 \ 0 \ 0 \ 241 \ 352 \ 1 \ 0 \ 0 \ 0 \ 0 \ 0 \ 25 \ 0 \ 0 \ 0 \ 7 \ 0 \ 0 \ 0 \ 242 \ 1 \ 0 \ 0 \ 25 \ 0 \ 0 \ 0 \ 251 \ 1 \ 0 \ 0“...,640)= 640 <0.000337>
 (234,“\ 4 \ 0S \ 0 \ 0 \ 0 \ 0 \ 0 \ 1 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 3 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0“...,256)= 256 <0.000096>
 poll([{fd = 234,events = POLLIN}],1,-1)= 1([{fd = 234,revents = POLLIN}])< 0.004 102>
 read(234,“\ 4 \ 20S \ 0 \ 0 \ 0 \ 0 \ 0 \ 1 \ 0 \ 0 \ 0!\ 1 \ 0 \ 0 \ 0 \ 0 \ 3 \ 0 \ 1 \ 0 \ 0 \ 0 \ 0 \ 10 \ 0 \ 0!\ 1 \ 0 \ 0“...,256)= 256 <0.000037>
 poll([{fd = 234,events = POLLIN}],1,-1)= 1([{fd = 234,revents = POLLIN}])<0.000157>
 (234,“\ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ t \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0“...,289)= 289 <0.000047>
 (234,“\ 4 \ 0S \ 0 \ 0 \ 0 \ 0 \ 0 \ 1 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 3 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0“...,256)= 256 <0.000036>
 poll([{fd = 234,events = POLLIN}],1,-1)= 1([{fd = 234,revents = POLLIN}])< 0.001 882>

讨论

即使ACE库有一个使用它的选项,移到epoll()也许没什么好处,因为在这种情况下poll()只被一个文件描述符调用。

当系统加载了600个奇数线程时,这个poll()调用占用了涉及进程的系统调用CPU时间的98%左右。 所以我正在寻找方法来提高效率。 但是,在write() poll()之后调用poll()会出现问题,因为它的调用速度比read()调用的速度慢100倍。

一个系统调用与另一个系统调用之间的时间差只是先例和下一个之间的时间差。 它只是一个测量目的时间戳,以便用户知道系统调用需要多less时间,并查明应用程序是否挂在某个系统调用上。

不过,我有点迷惑,看到这里的读取速度更快。 简单地说,因为写操作通常是asynchronous的,但是读操作往往是直线的,如果我们跳过不同的文件系统块,磁盘寻道可能会使其变慢。 但请参阅revents(请求的事件 – poll()调用中的第三个参数)是说POLLIN意味着要读取的数据。 也许这可能解释明显的缓慢。 尽pipe如此,我将需要整个strace来确定。

我相信我可能会有问题相信什么strace告诉我。 查看strace的源代码,我们可以看到当系统调用即将被input时,当前时间被捕获,并且当系统调用退出时捕获当前时间。

换句话说,strace正在测量进入和退出系统调用之间的挂钟时间。 这意味着它不会测量系统调用消耗了多lessCPU时间。 因此,阻止呼叫可能会占用应用程序的大部分系统时间,但是这是挂钟时间,与所使用的系统CPU数量无关。