zoukankan      html  css  js  c++  java
  • 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
    ", 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 }
  • 相关阅读:
    Mac下好玩的终端命令
    【bzoj3441】乌鸦喝水
    LeetCode[39]: 组合总和
    打击盗版,支持原创
    状态模式(State)-设计模式
    webpack核心概念
    吴裕雄--天生自然TensorFlow高层封装:Estimator-自定义模型
    吴裕雄--天生自然TensorFlow高层封装:Estimator-DNNClassifier
    吴裕雄--天生自然TensorFlow高层封装:Keras-TensorFlow API
    吴裕雄--天生自然TensorFlow高层封装:Keras-多输入输出
  • 原文地址:https://www.cnblogs.com/Jimmy104/p/5258205.html
Copyright © 2011-2022 走看看