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版本号比较函数 LooseVersion 和StrictVersion
- vsftpd启动报错:vsftpd:500 OOPS: bad bool value in config file for: anonymous_enable
vsftpd启动报错:vsftpd:500 OOPS: bad bool value in config file for: anonymous_enable 今天在调试centos vsftp的时 ...
- 分布式中 CAP BASE ACID 理解(转载)
概念理解(CAP,BASE, ACID) CAP CAP: Consistency, Availability, Partition-tolerance 强一致性(Consistency).系统在执 ...
- VS开发框架DevExtreme v19.1全解析!全新的UI小部件
行业领先的.NET界面控件DevExpress 正式发布了v19.1版本,本文将以系列文章的方式为大家介绍DevExtreme Complete Subscription v19.1中全新发布的Dro ...
- Kendo UI for jQuery使用教程:使用MVVM初始化(一)
[Kendo UI for jQuery最新试用版下载] Kendo UI目前最新提供Kendo UI for jQuery.Kendo UI for Angular.Kendo UI Support ...
- DevExpress ASP.NET Core v19.1版本亮点:数据网格和树列表
行业领先的.NET界面控件DevExpress 发布了v19.1版本,本文将以系列文章的方式为大家介绍DevExpress ASP.NET Core Controls v19.1中新增的一些控件及增强 ...
- vue中前进刷新、后退缓存方案收集
来源掘金: https://juejin.im/post/5b2ce07ce51d45588a7dbf76 来源博客园 https://www.cnblogs.com/wonyun/p/8763314 ...
- 【leetcode】1272. Remove Interval
题目如下: Given a sorted list of disjoint intervals, each interval intervals[i] = [a, b] represents the ...
- TTTTTTTTTTTTTTTTTT POJ 2724 奶酪消毒机 二分匹配 建图 比较难想
Purifying Machine Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 5004 Accepted: 1444 ...
- scrapy项目5:爬取ajax形式加载的数据,并用ImagePipeline保存图片
1.目标分析: 我们想要获取的数据为如下图: 1).每本书的名称 2).每本书的价格 3).每本书的简介 2.网页分析: 网站url:http://e.dangdang.com/list-WY1-dd ...