libco icon indicating copy to clipboard operation
libco copied to clipboard

epoll_wait 返回的时间不是固定1ms,有几率出现1-4秒的情况?

Open H2Z22017 opened this issue 7 years ago • 18 comments

在某个携程里用了poll(NULL, 0, msleep);来做定时,结果发现定时不准。msleep=10000的情况下有时候会出现12秒的延迟执行。最后定位到co_epoll_wait,好像不是固定阻塞1毫秒,有时候会阻塞1-4秒。整个测试代码就一个协程,内容仅仅是打印时间在屏幕,不会出现执行忙的情况。

H2Z22017 avatar Sep 07 '17 07:09 H2Z22017

epoll_wait的精度是这样,如果需要精确的1ms,一般的方案是用一个独立线程usleep来定期发通知给epoll线程

wechatsunny avatar Sep 07 '17 09:09 wechatsunny

哦,不是毫秒级别,是秒级的误差。见到一次最多4秒的延迟也是对的是吧?就是不能用来做定时器是吧?

H2Z22017 avatar Sep 07 '17 09:09 H2Z22017

不是,epoll_wait系统精度是1ms ~ 4ms,不会是秒级误差。 你的具体代码能否提供下?

wechatsunny avatar Sep 07 '17 09:09 wechatsunny

基本没什么功能了,就留了最简单的测试代码。 void DataCore::runServer() { stCoRoutine_t *db_co = nullptr; co_create(&db_co, nullptr, dealDBServer, 0); co_resume(db_co); co_eventloop(co_get_epoll_ct(), 0, 0);

} //定时调用的函数最后是在这里 void DataCore::onDealDBServer(void *arg) { co_enable_hook_sys(); //this->initDB();

while (true)
{
	fflush(stdout);
	fflush(stderr);

	
	int msleep = 10000;
	int tick = ServerDelegate::getInstance()->getServerTick();

	//int ret = getDB("server")->sql_fetch_cell_int("select UNIX_TIMESTAMP()");
	int ret = 9;
	fprintf(stderr, "get db query:%d,%d,%d,%d,%d\n", ret, ServerDelegate::getInstance()->getServerTime(), ServerDelegate::getInstance()->getServerTick() - tick, ServerDelegate::getInstance()->getLocalServerTime(),(int)time(nullptr));
	msleep -= ServerDelegate::getInstance()->getServerTick() - tick;
	fprintf(stderr, "%d\n", msleep);


	poll(NULL, 0, msleep);
}
return;

}

//改了co_eventloop配合打印日志。没修改其他任何代码。 void co_eventloop( stCoEpoll_t *ctx,pfn_co_eventloop_t pfn,void *arg ) { if( !ctx->result ) { ctx->result = co_epoll_res_alloc( stCoEpoll_t::_EPOLL_SIZE ); } co_epoll_res *result = ctx->result;

unsigned long long lastupdate = GetTickMS();
for (;;)
{
	unsigned long long lastupdate2 = GetTickMS();
	if (lastupdate2 - lastupdate >= 200)
		fprintf(stderr, "slow...........: %d\n", int(lastupdate2 - lastupdate));
	lastupdate = lastupdate2;

	int ret = co_epoll_wait(ctx->iEpollFd, result, stCoEpoll_t::_EPOLL_SIZE, 1);
	//usleep(1000);

	int debug = int(GetTickMS() - lastupdate2);

	if (debug >= 200)
	{

		fprintf(stderr, "slow0...........: %d\n", debug);
	}

"slow0...........: 开始正常,大概跑个1分钟就开始有200多毫秒的结果出来了,然后偶尔会有秒级别的出现。

H2Z22017 avatar Sep 07 '17 09:09 H2Z22017

对了,环境是vs2017调试本地的虚拟机centos 7内核是3.1的

H2Z22017 avatar Sep 07 '17 09:09 H2Z22017

能否在你的虚拟机上面单独写一个小程序,里面只是做epoll_wait的调用,不连接不适用libco,看会不会定期出现延迟的情况

wechatsunny avatar Sep 07 '17 09:09 wechatsunny

我试试

H2Z22017 avatar Sep 07 '17 09:09 H2Z22017

void DataCore::runServer() { //stCoRoutine_t *db_co = nullptr; //co_create(&db_co, nullptr, dealDBServer, 0); //co_resume(db_co); co_eventloop(co_get_epoll_ct(), 0, 0);

} 这样?什么都不做,然后就等,,,,简单了吧?

H2Z22017 avatar Sep 07 '17 09:09 H2Z22017

不是,我意思是你写一个小程序,不用链接libco,直接调用系统函数 epoll_wait fd = epoll_create(..);

for(;;) { struct epoll_event result;.. start = tick(); epoll_wait( .. 1 ); if( tick() - start > xx ) print ... }

wechatsunny avatar Sep 07 '17 09:09 wechatsunny

噢,理解了,我试试,你怀疑我环境问题是吧

H2Z22017 avatar Sep 07 '17 09:09 H2Z22017

因为其实co_epoll_wait就是只有epoll_wait调用

wechatsunny avatar Sep 07 '17 09:09 wechatsunny

看到了,所以我也想不通,怎么会有秒延迟出现。我先试试自己的环境,,,有问题的话再提给你。 你们测试用的环境是怎么样的?

H2Z22017 avatar Sep 07 '17 09:09 H2Z22017

这边是centos

wechatsunny avatar Sep 07 '17 09:09 wechatsunny

什么版本的? 6.5? 64位的吧

H2Z22017 avatar Sep 07 '17 09:09 H2Z22017

应该是虚拟机的问题,不带libco也会有这个问题,找个真机我再测试下,谢啦!

H2Z22017 avatar Sep 07 '17 12:09 H2Z22017

epoll_wait延时1-4秒的问题 您那边儿定位是什么问题了吗 最近我这个边 也遇到了这个问题

douya1018 avatar Sep 06 '23 06:09 douya1018

哩噶来件已经被我收埋佐啦哈哈 ^ ^

hobby avatar Sep 06 '23 06:09 hobby

@H2Z22017 epoll_wait延时1-4秒的问题 您那边儿定位是什么问题了吗 最近我这个边 也遇到了这个问题

douya1018 avatar Sep 06 '23 06:09 douya1018