针对自己写的一个服务器网络引擎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 ", 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 "); 111 } 112 else if(arrEvents[i].events & EPOLLERR) //socket disconnect 113 { 114 printf("EPOLLERR "); 115 } 116 else 117 { 118 //其他的处理 119 printf("EPOLL NUKNOW MSG "); 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 }