epoll 性能分析(解决占用CPU 过高问题)
针对自己写的一个服务器网络引擎Engine 文章后面附上源码
使用epoll 刚刚开始时候发现占用CPU 特别高,但是网络引擎里面基本没干什么事,不应该有这么高的CPU,一直不解,
于是自己慢慢的分析服务器工作线程,发现主要的性能消耗应该是处理IO 时候,
int nEventNum = epoll_wait(m_nEpId, arrEvents, default_epoll_size, );

原来是 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消耗过高,
/*---------------------------------------------------
Date: Feb 22, 2016
Author: fangjunmin
Modify:
Description: IO基类
----------------------------------------------------*/ #ifndef CBASEIO_H_
#define CBASEIO_H_
#include "cLink.h"
#include <queue> class cCommAIO;
class CommMsgArgs; class cBaseIO
{
public:
cBaseIO();
virtual ~cBaseIO(); bool start();
bool stop(); bool startEpoll();
bool stopEopll(); void processIOEvent(); virtual EF_EVENT_RESULT on_io_read(cLink * pLink){return EF_EVR_NORMAL;};
virtual EF_EVENT_RESULT on_io_write(cLink * pLink){return EF_EVR_NORMAL;};
void on_io_error(int fd, int32 sn); public: bool AddIoHandle(int32 fd, int32 sn, uint32 nEventType);
bool DelIoHandle(int32 fd, int32 sn);
bool ModIoHandle(int32 fd, int32 sn, uint32 nEventType); //bool request_message_send(CommMsgArgs & args);
bool request_connection_close(int fd, int32 sn);
bool request_connection_open(int fd, int32 sn); bool bind_comm_user(cCommAIO* pAIO); void fill_epoll_t(struct epoll_event & ep_t, int32 ev_type, cLink * pLink); protected:
//void process_internal_command();
void process_io_event();
//void process_timer(int64 now_time/*ms*/, TIMER_QUEUE & timer_q, TIMER_INDEX_MAP & timer_index_map);
//void process_g_send_q(); protected:
cCommAIO* m_pAIO;
vecLink m_vecLink;//所有的客户端链接
int32 m_nEpId; //epoll id mapLink m_mapLink;
int32 m_nExistIONum; }; #endif /* CCOMMMOUDLE_H_ */
/*---------------------------------------------------
Date: Feb 22, 2016
Author: fangjunmin
Modify:
Description:
----------------------------------------------------*/ #include "cBaseIO.h"
#include "sys/epoll.h"
#include <queue>
#include "../thread/simple_lock.h"
#include "../Frame/cCommAIO.h"
#include "../inlc/globalConfig.h" cBaseIO::cBaseIO()
{
// TODO Auto-generated constructor stub
m_pAIO = NULL;
m_nEpId = ;
m_nExistIONum = ;
} cBaseIO::~cBaseIO()
{
// TODO Auto-generated destructor stub
} bool cBaseIO::start()
{
startEpoll();
return true;
} bool cBaseIO::stop()
{
stopEopll();
return true;
} bool cBaseIO::startEpoll()
{
m_nEpId = epoll_create(default_epoll_size);
if(m_nEpId == -)
{
pthread_exit(NULL);
return false;
}
return true;
} bool cBaseIO::stopEopll()
{
return true;
} void cBaseIO::processIOEvent()
{
epoll_event arrEvents[default_epoll_size + ];
int nEventNum = epoll_wait(m_nEpId, arrEvents, default_epoll_size, );
for(int i=; i<nEventNum; ++i)
{
printf("event num is: %d\n", nEventNum);
cLink * pLink = (cLink *)arrEvents[i].data.ptr;
if( == pLink)
{
continue;
} if( arrEvents[i].events & EPOLLIN ) //接收到数据,读socket
{
if(on_io_read(pLink) == EF_EVR_DEL_IO)
{
pLink->m_eStat = EF_IO_ERROR;
on_io_error(pLink->_fd, pLink->_sn);
DelIoHandle(pLink->_fd, pLink->_sn);
continue;
}
}
else if(arrEvents[i].events & EPOLLOUT) //有数据待发送,写socket
{
switch(on_io_write(pLink))
{
case EF_EVR_DEL_IO:
{
pLink->m_eStat = EF_IO_ERROR;
on_io_error(pLink->_fd, pLink->_sn);
DelIoHandle(pLink->_fd, pLink->_sn); continue;
}
break;
case EF_EVR_TX_EAGAIN:
{
continue;
}
break;
default:
{
pLink->m_eStat = EF_IO_NORMAL;
uint32 type = EF_EVT_READ;
ModIoHandle(pLink->_fd, pLink->_sn, type);
}
break;
}
}
else if(arrEvents[i].events & EPOLLHUP) //socket disconnect
{
printf("EPOLLHUP\n");
}
else if(arrEvents[i].events & EPOLLERR) //socket disconnect
{
printf("EPOLLERR\n");
}
else
{
//其他的处理
printf("EPOLL NUKNOW MSG \n");
}
}
} //void cBaseIO::process_internal_command()
//{
// int32 nLoopSize = 0;
// {
// SimpleLock lock;;
// nLoopSize = m_queueInterCmd.size();
// }
//
// for(int32 i = 0; i < nLoopSize; ++i)
// {
// EF_INTER_CMD * cmd(NULL);
// {
// SimpleLock lock;;
// cmd = m_queueInterCmd.front();
// m_queueInterCmd.pop();
// }
//
// if(!cmd)
// {
// continue;
// }
//
// switch(cmd->_type)
// {
//// case EF_IC_ADD_TIMER:
//// {
//// timer_add(ic, now_time, timer_q, timer_index_map);
//// }
//// break;
//// case EF_IC_DEL_TIMER:
//// {
//// timer_del(ic, now_time, timer_q, timer_index_map);
//// }
// break;
// case EF_IC_ADD_IO:
// {
// io_add(cmd);
// }
// break;
// case EF_IC_DEL_IO:
// {
// io_del(cmd);
// }
// break;
// case EF_IC_MOD_IO:
// {
// io_mod(cmd);
// }
// break;
//// case EF_IC_CHK_IO:
//// {
//// io_chk(ic, epfd, ioevent_index_map);
//// }
// break;
// default:
// break;
// }
//
// delete cmd;
// }
//} bool cBaseIO::AddIoHandle(int32 fd, int32 sn, uint32 nEventType)
{
if(!(nEventType & EF_EVT_READ) && !(nEventType & EF_EVT_WRITE))
{
return false;
} itmapLink it = m_mapLink.find( fd);
if(it != m_mapLink.end())
{
return false;
}
cLink *pLink = new cLink();
if(!pLink)
{
on_io_error(pLink->_fd, pLink->_sn);
return false;
}
pLink->_fd = fd;
pLink->_sn = sn; struct epoll_event ep_t;
fill_epoll_t(ep_t, nEventType, pLink); if(epoll_ctl(m_nEpId, EPOLL_CTL_ADD, pLink->_fd, &ep_t) == -)
{
on_io_error(pLink->_fd, pLink->_sn);
delete pLink;
}
else
{
std::cout << "[FD] ADD " << pLink->_fd << ":" << pLink->_sn << std::endl; m_mapLink[pLink->_fd] = pLink;
__sync_add_and_fetch(&m_nExistIONum, );
} return true;
} void cBaseIO::fill_epoll_t(struct epoll_event & ep_t, int32 ev_type, cLink * pLink)
{
ep_t.data.ptr = pLink;
ep_t.events = EPOLLET | EPOLLHUP | EPOLLERR; if(ev_type & EF_EVT_READ)
{
ep_t.events |= EPOLLIN;
} if(ev_type & EF_EVT_WRITE)
{
ep_t.events |= EPOLLOUT;
}
} bool cBaseIO::DelIoHandle(int32 fd, int32 sn)
{
itmapLink it = m_mapLink.find( fd);
if(it == m_mapLink.end())
{
return false;
}
cLink *pLink = it->second;
if(!pLink)
{
return false;
}
if(epoll_ctl(m_nEpId, EPOLL_CTL_DEL, pLink->_fd, NULL) == -)
{
return false;
}
m_mapLink.erase(pLink->_fd);
close(fd); __sync_sub_and_fetch(&m_nExistIONum, );
std::cout << "[FD] DEL " << pLink->_fd << ":" << pLink->_sn << std::endl; return true;
} bool cBaseIO::ModIoHandle(int32 fd, int32 sn, uint32 nEventType)
{
itmapLink it = m_mapLink.find(fd);
if(it != m_mapLink.end())
{
return false;
}
cLink *pLink = it->second;
if(!pLink)
{
return false;
}
struct epoll_event ep_t;
fill_epoll_t(ep_t, nEventType, pLink); if(epoll_ctl(m_nEpId, EPOLL_CTL_MOD, pLink->_fd, &ep_t) == -)
{
on_io_error(pLink->_fd, pLink->_sn);
DelIoHandle(pLink->_fd, pLink->_sn);
return false;
}
std::cout << "[FD] MOD " << pLink->_fd << ":" << pLink->_sn << std::endl;
return true;
} //
//bool cBaseIO::io_add(EF_INTER_CMD * ic)
//{
// if(!ic)
// {
// return false;
// }
//
// itmapLink it = m_mapLink.find(ic->_info.fd);
// if(it != m_mapLink.end())
// {
// return false;
// }
// cLink *pLink = new cLink();
// if(pLink)
// {
// on_io_error(pLink->_fd, pLink->_sn);
// return false;
// }
// pLink->_fd = ic->_info.fd;
// pLink->_sn = ic->_info.sn;
//
//
// struct epoll_event ep_t;
// //fill_epoll_t(ep_t, n->_type, n);
//
// if(epoll_ctl(m_nEpId, EPOLL_CTL_ADD, pLink->_fd, &ep_t) == -1)
// {
// on_io_error(pLink->_fd, pLink->_sn);
// delete pLink;
// }
// else
// {
// std::cout << "[FD] ADD " << pLink->_fd << ":" << pLink->_sn << std::endl;
//
// m_mapLink[pLink->_fd] = pLink;
// __sync_add_and_fetch(&m_nExistIONum, 1);
// }
//
//
// return true;
//} //bool cBaseIO::request_message_send(CommMsgArgs & args)
//{
// send_message_process(&args);
// return true;
//} bool cBaseIO::request_connection_close(int fd, int32 sn)
{
return DelIoHandle(fd, sn);
} bool cBaseIO::request_connection_open(int fd, int32 sn)
{
AddIoHandle(fd, sn ,EF_EVT_READ);
return true;
} bool cBaseIO::bind_comm_user(cCommAIO* pAIO)
{
m_pAIO = pAIO;
return true;
} void cBaseIO::on_io_error(int fd, int32 sn)
{
m_pAIO->notice_connection_close(fd, sn);
}
epoll 性能分析(解决占用CPU 过高问题)的更多相关文章
- epoll 性能分析(解决占用CPU 过高问题)2
针对服务器框架Engine,在工作线程中发现该线程占用CPU过高,分析之后发现问题出在死循环那里 void cServerBase::OnProcess() { printf("cServe ...
- linux 分析进程占用CPU过高
重点是查看进程的线程中,哪个线程占用cpu过高,然后用gdb附加到进程,调试线程,看是否有死循环或者死锁等问题,步骤如下: 1 先用ps + grep找出该死的进程pid,比如 1706 2 top ...
- Windows服务器java.exe占用CPU过高问题分析及解决
最近在测试一个用java语言实现的数据采集接口时发现,接口一旦运行起来,CPU利用率瞬间飙升到85%-95%,一旦停止就恢复到40%以下,这让我不得不面对以前从未关注过的程序性能问题. 在硬着头皮查找 ...
- memcache占用CPU过高的解决办法
Simon最近为公司服务器操碎了心 , 先是mysqld进程占用CPU过高 , 导致服务器性能变低 ,网站打开太慢.通过增加max_connections及table_cache解决了问题 ,随后发现 ...
- 再记一次w3wp占用CPU过高的解决过程(Dictionary和线程安全)
在此之前项目有发生过两次类似的状况,都得以解决,但最近又会发现偶尔CPU会跑满,虽然之前使用过WinDbg解决过两次问题但人的记忆是不可靠的,今天处理同样问题的时候还是遇到了一些障碍,这一次希望可以记 ...
- Mysql占用CPU过高如何优化,如何解决
2017-02-28 15:13 331人阅读 评论(0) 收藏 举报 MySQL占用CPU过高如何优化 一次生产DB服务器的 超负荷运行问题解决: 1.查看生产DB服务器top列表, 执行 to ...
- SQL Server 占用CPU较高的解决方法
触发原因:月底系统结账的时候对ERP的操作较多,有用户反馈系统之间的数据传输很久没有同步.随即到服务器上查看,没有发现有程序导致的问题,看了一下CPU的使用率,发现SQL Server占用率在百分之九 ...
- Linux排查Java程序占用CPU很高的解决办法
Java的工具集相当强大,学习成本也很低,处理线上问题时,jstack这个工具就比微软的windbg,好学好用很多,3步找出占用CPU很高的源所在.而windbg反人类的各种命令,实在不敢恭维. 故意 ...
- w3wp占用CPU过高
w3wp占用CPU过高 在此之前项目有发生过两次类似的状况,都得以解决,但最近又会发现偶尔CPU会跑满,虽然之前使用过WinDbg解决过两次问题但人的记忆是不可靠的,今天处理同样问题的时候还是遇到了一 ...
随机推荐
- python生成器并行实例
生成器并行实例: send发送值被yield接受到赋值给baozi变量 #yield作用只是在这里保存这个值的当前状态然后返回之后在调用next,又回到yield #单纯调用next不会给yield传 ...
- Mongodb的聚合和管道
MongoDB 聚合 MongoDB中聚合(aggregate)主要用于处理数据(诸如统计平均值,求和等),并返回计算后的数据结果. aggregate() 方法 MongoDB中聚合的方法使用agg ...
- 在Nginx中使用Godaddy的SSL证书
首先在Godaddy付款购买SSL证书,成功之后打开管理面板,找到刚购买的SSL证书,点击新建证书,这个时候Godaddy会让提供CSR文件内容,可以通过下面的命令行生成csr内容: openssl ...
- 使用SpringAOP实现事务(声明式事务管理、零配置)
前言: 声明式事务管理建立在AOP之上的.其本质是对方法前后进行拦截,然后在目标方法开始之前创建或者加入一个事务,在执行完目标方法之后根据执行情况提交或者回滚事务.声明式事务最大的优点就是不需要通过编 ...
- C#创建泛型类T的实例的三种方法
原文链接:https://www.cnblogs.com/lxhbky/p/6020612.html 方法一,通过外部方法传入的实例来实例化: //泛型类: public class MySQLHel ...
- pymysql操作数据库、索引、慢日志管理
目录 pymysql操作数据库 简单操作 sql的注入问题 sql注入问题解决办法 sql注入问题模板总结 利用pymysql操作数据库 (增删改),conn.commit() 索引 1.为何要有索引 ...
- 4.2 会议室预定系统,ajax参数(未完成)
参考blog https://www.cnblogs.com/alice-bj/p/9191082.html https://www.cnblogs.com/yuanchenqi/articles/7 ...
- Spring CommonsMultipartResolver 上传文件
转:http://yanglei008.iteye.com/blog/246920 ...Controller...{ // 创建一个通用的多部分解析器 CommonsMultipartResolve ...
- Word:转换PDF
本文适用于Word 2007 + Windows 7,造冰箱的大熊猫@cnblogs 2018/8/3 一.Word文档转PDF文档 把Word文档转换为PDF,有两个免费解决方案 1.Microso ...
- D. Tokitsukaze, CSL and Stone Game ( 取石子游戏?no,更像棋盘游戏 )
去吧,皮皮虾 题意: 有 n 堆石子,每堆有 a[ i ] 个,然后每次 操作 可以选择任意一堆 石子,取走一个. 若你取完了之后,存在两堆石子,他们的个数一样多,你就输了( 包括两堆都是0个), ...