epoll 性能分析(解决占用CPU 过高问题)

针对自己写的一个服务器网络引擎Engine 文章后面附上源码

使用epoll  刚刚开始时候发现占用CPU 特别高,但是网络引擎里面基本没干什么事,不应该有这么高的CPU,一直不解,

于是自己慢慢的分析服务器工作线程,发现主要的性能消耗应该是处理IO 时候,

int nEventNum = epoll_wait(m_nEpId, arrEvents, default_epoll_size, 0);

 

原来是 epoll_wait的最后一个参数的问题

 int epoll_wait(int epfd, struct epoll_event * events, int maxevents, int timeout);
等待事件的产生,类似于select()调用。

参数events用来从内核得到事件的集合,maxevents告之内核这个events有多大,

这个 maxevents的值不能大于创建epoll_create()时的size,

参数timeout是超时时间(毫秒,0会立即返回,-1将不确定,也有说法说是永久阻塞)。

该函数返回需要处理的事件数目,如返回0表示已超时。

 

于是我把参数timeout改成 1 毫秒,CPU 就降下来了,

int nEventNum = epoll_wait(m_nEpId, arrEvents, default_epoll_size, 1);

 

体会:

      如果超时时间为0,必然导致内核不停的调用epoll_wait函数,频率应该是内核的最小时间粒度,其结果是

相当于一个死循环调用了,所以导致CPU消耗过高,

 

 

 1 /*---------------------------------------------------
 2  Date:                     Feb 22, 2016
 3  Author:                 fangjunmin
 4  Modify:                
 5  Description:            IO基类
 6  ----------------------------------------------------*/
 7 
 8 #ifndef CBASEIO_H_
 9 #define CBASEIO_H_
10 #include "cLink.h"
11 #include <queue>
12 
13 
14 
15 class cCommAIO;
16 class CommMsgArgs;
17 
18 
19 
20 
21 class cBaseIO
22 {
23 public:
24     cBaseIO();
25     virtual ~cBaseIO();
26 
27     bool start();
28     bool stop();
29 
30 
31     bool startEpoll();
32     bool stopEopll();
33 
34     void processIOEvent();
35 
36     virtual EF_EVENT_RESULT on_io_read(cLink * pLink){return EF_EVR_NORMAL;};
37     virtual EF_EVENT_RESULT on_io_write(cLink * pLink){return EF_EVR_NORMAL;};
38     void on_io_error(int fd, int32 sn);
39 
40 public:
41 
42     bool AddIoHandle(int32 fd, int32 sn, uint32 nEventType);
43     bool DelIoHandle(int32 fd, int32 sn);
44     bool ModIoHandle(int32 fd, int32 sn, uint32 nEventType);
45 
46     //bool request_message_send(CommMsgArgs & args);
47     bool request_connection_close(int fd, int32 sn);
48     bool request_connection_open(int fd, int32 sn);
49 
50     bool bind_comm_user(cCommAIO* pAIO);
51 
52     void fill_epoll_t(struct epoll_event & ep_t, int32 ev_type, cLink * pLink);
53 
54 protected:
55     //void process_internal_command();
56     void process_io_event();
57     //void process_timer(int64 now_time/*ms*/, TIMER_QUEUE & timer_q, TIMER_INDEX_MAP & timer_index_map);
58     //void process_g_send_q();
59 
60 protected:
61     cCommAIO*     m_pAIO;
62     vecLink        m_vecLink;//所有的客户端链接
63     int32        m_nEpId;  //epoll id
64 
65 
66     mapLink                        m_mapLink;
67     int32                         m_nExistIONum;
68 
69 
70 };
71 
72 
73 #endif /* CCOMMMOUDLE_H_ */

 

 

  1 /*---------------------------------------------------
  2  Date:                     Feb 22, 2016
  3  Author:                 fangjunmin
  4  Modify:                
  5  Description:            
  6  ----------------------------------------------------*/
  7 
  8 #include "cBaseIO.h"
  9 #include "sys/epoll.h"
 10 #include <queue>
 11 #include "../thread/simple_lock.h"
 12 #include "../Frame/cCommAIO.h"
 13 #include "../inlc/globalConfig.h"
 14 
 15 cBaseIO::cBaseIO()
 16 {
 17     // TODO Auto-generated constructor stub
 18     m_pAIO = NULL;
 19     m_nEpId = 0;
 20     m_nExistIONum = 0;
 21 }
 22 
 23 cBaseIO::~cBaseIO()
 24 {
 25     // TODO Auto-generated destructor stub
 26 }
 27 
 28 
 29 bool cBaseIO::start()
 30 {
 31     startEpoll();
 32     return true;
 33 }
 34 
 35 bool cBaseIO::stop()
 36 {
 37     stopEopll();
 38     return true;
 39 }
 40 
 41 
 42 bool cBaseIO::startEpoll()
 43 {
 44     m_nEpId = epoll_create(default_epoll_size);
 45     if(m_nEpId == -1)
 46     {
 47         pthread_exit(NULL);
 48         return false;
 49     }
 50     return true;
 51 }
 52 
 53 bool cBaseIO::stopEopll()
 54 {
 55     return true;
 56 }
 57 
 58 void cBaseIO::processIOEvent()
 59 {
 60     epoll_event arrEvents[default_epoll_size + 1];
 61     int nEventNum = epoll_wait(m_nEpId, arrEvents, default_epoll_size, 0);
 62     for(int i=0; i<nEventNum; ++i)
 63     {
 64         printf("event num is:  %d\n", nEventNum);
 65         cLink * pLink = (cLink *)arrEvents[i].data.ptr;
 66         if(0 == pLink)
 67         {
 68             continue;
 69         }
 70 
 71         if( arrEvents[i].events & EPOLLIN ) //接收到数据,读socket
 72         {
 73             if(on_io_read(pLink) == EF_EVR_DEL_IO)
 74             {
 75                 pLink->m_eStat = EF_IO_ERROR;
 76                 on_io_error(pLink->_fd, pLink->_sn);
 77                 DelIoHandle(pLink->_fd, pLink->_sn);
 78                 continue;
 79             }
 80         }
 81         else if(arrEvents[i].events & EPOLLOUT) //有数据待发送,写socket
 82         {
 83             switch(on_io_write(pLink))
 84             {
 85                 case EF_EVR_DEL_IO:
 86                 {
 87                     pLink->m_eStat = EF_IO_ERROR;
 88                     on_io_error(pLink->_fd, pLink->_sn);
 89                     DelIoHandle(pLink->_fd, pLink->_sn);
 90 
 91                     continue;
 92                 }
 93                     break;
 94                 case EF_EVR_TX_EAGAIN:
 95                 {
 96                     continue;
 97                 }
 98                     break;
 99                 default:
100                 {
101                     pLink->m_eStat = EF_IO_NORMAL;
102                     uint32 type = EF_EVT_READ;
103                     ModIoHandle(pLink->_fd, pLink->_sn, type);
104                 }
105                 break;
106             }
107         }
108         else if(arrEvents[i].events & EPOLLHUP) //socket disconnect
109         {
110             printf("EPOLLHUP\n");
111         }
112         else if(arrEvents[i].events & EPOLLERR) //socket disconnect
113         {
114             printf("EPOLLERR\n");
115         }
116         else
117         {
118            //其他的处理
119             printf("EPOLL NUKNOW MSG \n");
120         }
121     }
122 }
123 
124 //void cBaseIO::process_internal_command()
125 //{
126 //    int32 nLoopSize = 0;
127 //    {
128 //        SimpleLock lock;;
129 //        nLoopSize = m_queueInterCmd.size();
130 //    }
131 //
132 //    for(int32 i = 0; i < nLoopSize; ++i)
133 //    {
134 //        EF_INTER_CMD * cmd(NULL);
135 //        {
136 //            SimpleLock lock;;
137 //            cmd = m_queueInterCmd.front();
138 //            m_queueInterCmd.pop();
139 //        }
140 //
141 //        if(!cmd)
142 //        {
143 //            continue;
144 //        }
145 //
146 //        switch(cmd->_type)
147 //        {
148 ////            case EF_IC_ADD_TIMER:
149 ////            {
150 ////                timer_add(ic, now_time, timer_q, timer_index_map);
151 ////            }
152 ////                break;
153 ////            case EF_IC_DEL_TIMER:
154 ////            {
155 ////                timer_del(ic, now_time, timer_q, timer_index_map);
156 ////            }
157 //                break;
158 //            case EF_IC_ADD_IO:
159 //            {
160 //                io_add(cmd);
161 //            }
162 //                break;
163 //            case EF_IC_DEL_IO:
164 //            {
165 //                io_del(cmd);
166 //            }
167 //                break;
168 //            case EF_IC_MOD_IO:
169 //            {
170 //                io_mod(cmd);
171 //            }
172 //                break;
173 ////            case EF_IC_CHK_IO:
174 ////            {
175 ////                io_chk(ic, epfd, ioevent_index_map);
176 ////            }
177 //                break;
178 //            default:
179 //                break;
180 //        }
181 //
182 //        delete cmd;
183 //    }
184 //}
185 
186 
187 
188 bool cBaseIO::AddIoHandle(int32 fd, int32 sn, uint32 nEventType)
189 {
190     if(!(nEventType & EF_EVT_READ) && !(nEventType & EF_EVT_WRITE))
191     {
192         return false;
193     }
194 
195 
196     itmapLink it = m_mapLink.find( fd);
197     if(it != m_mapLink.end())
198     {
199         return false;
200     }
201     cLink *pLink = new cLink();
202     if(!pLink)
203     {
204         on_io_error(pLink->_fd, pLink->_sn);
205         return false;
206     }
207     pLink->_fd = fd;
208     pLink->_sn = sn;
209 
210 
211     struct epoll_event ep_t;
212     fill_epoll_t(ep_t, nEventType, pLink);
213 
214     if(epoll_ctl(m_nEpId, EPOLL_CTL_ADD, pLink->_fd, &ep_t) == -1)
215     {
216         on_io_error(pLink->_fd, pLink->_sn);
217         delete pLink;
218     }
219     else
220     {
221         std::cout << "[FD] ADD " << pLink->_fd << ":" << pLink->_sn << std::endl;
222 
223         m_mapLink[pLink->_fd] = pLink;
224         __sync_add_and_fetch(&m_nExistIONum, 1);
225     }
226 
227 
228     return true;
229 }
230 
231 void cBaseIO::fill_epoll_t(struct epoll_event & ep_t, int32 ev_type, cLink * pLink)
232 {
233     ep_t.data.ptr = pLink;
234     ep_t.events = EPOLLET | EPOLLHUP | EPOLLERR;
235 
236     if(ev_type & EF_EVT_READ)
237     {
238         ep_t.events |= EPOLLIN;
239     }
240 
241     if(ev_type & EF_EVT_WRITE)
242     {
243         ep_t.events |= EPOLLOUT;
244     }
245 }
246 
247 bool cBaseIO::DelIoHandle(int32 fd, int32 sn)
248 {
249     itmapLink it = m_mapLink.find( fd);
250     if(it == m_mapLink.end())
251     {
252         return false;
253     }
254     cLink *pLink = it->second;
255     if(!pLink)
256     {
257         return false;
258     }
259     if(epoll_ctl(m_nEpId, EPOLL_CTL_DEL, pLink->_fd, NULL) == -1)
260     {
261         return false;
262     }
263     m_mapLink.erase(pLink->_fd);
264     close(fd);
265 
266     __sync_sub_and_fetch(&m_nExistIONum, 1);
267     std::cout << "[FD] DEL " << pLink->_fd << ":" << pLink->_sn << std::endl;
268 
269     return true;
270 }
271 
272 bool cBaseIO::ModIoHandle(int32 fd, int32 sn, uint32 nEventType)
273 {
274     itmapLink it = m_mapLink.find(fd);
275     if(it != m_mapLink.end())
276     {
277         return false;
278     }
279     cLink *pLink = it->second;
280     if(!pLink)
281     {
282         return false;
283     }
284     struct epoll_event ep_t;
285     fill_epoll_t(ep_t, nEventType, pLink);
286 
287     if(epoll_ctl(m_nEpId, EPOLL_CTL_MOD, pLink->_fd, &ep_t) == -1)
288     {
289         on_io_error(pLink->_fd, pLink->_sn);
290         DelIoHandle(pLink->_fd, pLink->_sn);
291         return false;
292     }
293     std::cout << "[FD] MOD " << pLink->_fd << ":" << pLink->_sn << std::endl;
294     return true;
295 }
296 
297 //
298 //bool cBaseIO::io_add(EF_INTER_CMD * ic)
299 //{
300 //    if(!ic)
301 //    {
302 //        return false;
303 //    }
304 //
305 //    itmapLink it = m_mapLink.find(ic->_info.fd);
306 //    if(it != m_mapLink.end())
307 //    {
308 //        return false;
309 //    }
310 //    cLink *pLink = new cLink();
311 //    if(pLink)
312 //    {
313 //        on_io_error(pLink->_fd, pLink->_sn);
314 //        return false;
315 //    }
316 //    pLink->_fd = ic->_info.fd;
317 //    pLink->_sn = ic->_info.sn;
318 //
319 //
320 //    struct epoll_event ep_t;
321 //    //fill_epoll_t(ep_t, n->_type, n);
322 //
323 //    if(epoll_ctl(m_nEpId, EPOLL_CTL_ADD, pLink->_fd, &ep_t) == -1)
324 //    {
325 //        on_io_error(pLink->_fd, pLink->_sn);
326 //        delete pLink;
327 //    }
328 //    else
329 //    {
330 //        std::cout << "[FD] ADD " << pLink->_fd << ":" << pLink->_sn << std::endl;
331 //
332 //        m_mapLink[pLink->_fd] = pLink;
333 //        __sync_add_and_fetch(&m_nExistIONum, 1);
334 //    }
335 //
336 //
337 //    return true;
338 //}
339 
340 //bool cBaseIO::request_message_send(CommMsgArgs & args)
341 //{
342 //    send_message_process(&args);
343 //    return true;
344 //}
345 
346 bool cBaseIO::request_connection_close(int fd, int32 sn)
347 {
348     return DelIoHandle(fd, sn);
349 }
350 
351 bool cBaseIO::request_connection_open(int fd, int32 sn)
352 {
353     AddIoHandle(fd, sn ,EF_EVT_READ);
354     return true;
355 }
356 
357 
358 bool cBaseIO::bind_comm_user(cCommAIO* pAIO)
359 {
360     m_pAIO = pAIO;
361     return true;
362 }
363 
364 
365 void cBaseIO::on_io_error(int fd, int32 sn)
366 {
367     m_pAIO->notice_connection_close(fd, sn);
368 }

 

posted @ 2016-03-09 14:57  树梢流年  阅读(13427)  评论(0编辑  收藏  举报