您的位置:首页 > 其它

strace问题定位

2014-03-09 14:19 141 查看
问题:

进程CPU占用率100%,用strace查看进程系统调用情况,发现madvise调用占90%的时间(正常情况下应以clockgettime,epoll_wait,epoll_ctl为主)。系统日志中有channel overflow错误,状态日志中显示channel的write调用有大量返回失败。

代码走读:

基础库代码中将数据传输通道,如socket,fifo,shm等抽象成channel,channel通过文件描述符读取数据,每个进程中所有的channel由统一的event loop维护。

Channel上有数据写发生时,并不直接在fd上调用write,而是先将数据写到channel中的buffer,然后根据某种规则将buffer中的数据通过fd上的write调用写出:



Buffer是堆上动态分配的存储空间,由起始地址、读位置和写位置(read index和write index,读和写相对于起始地址的偏移量,不是指针)来维护,当读写位置重合时,buffer不可读,当写空间不够时,重新分配更大的空间(2倍),将已有的数据拷贝至新位置,然后再写:



两个buffer维护操作:

DiscardReadedBytes:内存搬移,腾出更大的写空间



Compact:释放多余的空间,只保留buffer中没有读的数据



Channel写数据流程:



Flush流程:



流程优化:

Channel overflow时,可以先尝试将channel buffer中的数据调用C库的write,减少buffer中可读数据大小,再返回错误。

Flush流程中channel buffer数据通过C库调用系统调用写入内核,可读数据减少后,连续调用DiscardReadedBytes和Compact,造成对大块数据进行memmove和memcpy,compact操作可以加条件判断。

内存分配库的影响:

通过jemalloc分配内存时,连续memmove和memcpy会造成大量madvise系统调用,用C库默认的内存分配器不会出现这个问题。

修改:

Flush调用中的Compact加条件判断,buffer空间大于某个值才进行compact。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: