找回密码
 用户注册

QQ登录

只需一步,快速开始

查看: 10732|回复: 22

[求助] ACE_High_Res_Timer的问题,用了后定时器会不准

[复制链接]
发表于 2009-1-6 11:10:00 | 显示全部楼层 |阅读模式
我程序里有个600秒的定时器,实际执行时却是8分20秒的间隔。

如果把程序初始化时调用的下面这行删除掉定时器就准了,为啥?

ACE_Reactor::instance()->timer_queue()->gettimeofday(&ACE_High_Res_Timer::gettimeofday_hr);

我使用ACE_High_Res_Timer的目的主要是避免系统时间变动对程序的运行造成影响。
 楼主| 发表于 2009-1-8 09:55:20 | 显示全部楼层
顶一下,比较奇怪的问题,都不知道怎么判断原因所在。。。

代码中基本只用schedule_timer和cancel_timer。
发表于 2009-1-9 13:58:55 | 显示全部楼层
经过测试,没有发现你说的情况,测试代码如下:
#include "ace/Timer_Queue.h"
#include "ace/Reactor.h"
#include "ace/High_Res_Timer.h"
#include "ace/Trace.h"
#include "ace/Recursive_Thread_Mutex.h"
#include "ace/Log_Msg.h"

ACE_Time_Value g_begin_time, g_end_time;

class CTimerHrTest: public ACE_Event_Handler
{
public:
int open()
{
  ACE_Time_Value timer_interval(600);
  m_timer_id = ACE_Reactor::instance ()->schedule_timer(this, 0, timer_interval, timer_interval);
  g_begin_time = ACE_OS::gettimeofday();
  ACE_Time_Value tm = ACE_High_Res_Timer::gettimeofday_hr();
  ACE_DEBUG((LM_DEBUG, ACE_TEXT("begin absolute timer: %d\n"), g_begin_time.sec()));
  ACE_DEBUG((LM_DEBUG, ACE_TEXT("begin tick timer: %d\n"), tm.sec() ));
  if ( m_timer_id == -1 )
  {
   ACE_ERROR_RETURN((LM_ERROR, "%p\n", "schedule_timer failed."),-1);
  }
  return 0;
}

virtual int handle_timeout(const ACE_Time_Value &tm, const void *)
{
  // ACE_Time_Value tmp = tm - g_begin_time;
  g_end_time = ACE_OS::gettimeofday();
  
  ACE_DEBUG((LM_DEBUG, ACE_TEXT("end absolute timer: %d\n"),
          (g_end_time.sec() - g_begin_time.sec()) ));
  
  ACE_DEBUG((LM_DEBUG, ACE_TEXT("end tick timer: %d\n"), tm.sec() ));
  return 0;
}
virtual int handle_close()
{
  ACE_Reactor::instance ()->cancel_timer(m_timer_id);
  delete this;
  return 0;
}
private:
long m_timer_id;
};


int ACE_TMAIN(int argc, ACE_TCHAR **argv)
{
ACE_High_Res_Timer::global_scale_factor ();
// test timer source
ACE_Reactor::instance()->timer_queue()->gettimeofday(&ACE_High_Res_Timer::gettimeofday_hr);
CTimerHrTest timer_test;
if ( timer_test.open() == -1 )
{
  ACE_DEBUG(( LM_DEBUG, ACE_TEXT("(%t) Timer_open failed\n") ));
  return -1;
}
ACE_Reactor::instance()->run_event_loop();
}

测试结果: (Linux AS 4u5)
begin absolute timer: 1231479901
begin tick timer: 170079
end absolute timer: 600
end tick timer: 170679
 楼主| 发表于 2009-1-13 12:41:29 | 显示全部楼层

回复 #3 dwh0403 的帖子

试了一下你的代码:

begin absolute timer: 1231819410
begin tick timer: 92338
end absolute timer: 600
end tick timer: 93054
end absolute timer: 1085
end tick timer: 93631
end absolute timer: 1591
end tick timer: 94236
end absolute timer: 2094
end tick timer: 94835

。。。奇怪了,从absolute timer来看,和我说的8分多钟差不多,但那个tick timer看上去倒是600左右

[ 本帖最后由 Youth 于 2009-1-13 12:46 编辑 ]
 楼主| 发表于 2009-1-13 13:26:13 | 显示全部楼层

又运行了一次,可重复性挺好

begin absolute timer: 1231822038
begin tick timer: 95473
end absolute timer: 600
end tick timer: 96188
end absolute timer: 1085
end tick timer: 96766
end absolute timer: 1592
end tick timer: 97371
end absolute timer: 2094
end tick timer: 97969
 楼主| 发表于 2009-1-15 13:06:16 | 显示全部楼层
继续顶。。。补充一下我的开发环境了:win xp sp3, vc8sp1, ace 5.6.1
 楼主| 发表于 2009-11-19 15:32:23 | 显示全部楼层
大半年后再来顶一次,本来已经放下这个问题了,最新发现:

2台双核笔记本上有问题。
2台单核超线程台式机上没问题。

是我用法不对吗?
发表于 2009-11-27 15:43:34 | 显示全部楼层
ACE_High_Res_Timer是根据cpu的tick来计算的
双核的有问题,单核没问题,可能跟cpu或者os的tick计算方法有关。
很可能是ACE考虑的还不够全面。跟一下源码吧,应该不复杂。
发表于 2009-12-29 13:51:12 | 显示全部楼层
这个问题我也遇到了,
为了解决系统时钟调整之后定时器的延时响应的问题,
引入了高精度定时器。结果测试却发现,
双核机器上导致ACE提供的定时器时钟不准的问题。
尝试使用单线程运行定时器,并设置到一个CPU上运行,效果也不甚理想。
有时间的话是得看看源代码实现,或者看看新版本是否有解决这个问题。
发表于 2009-12-31 15:58:52 | 显示全部楼层
正好我也遇到这样的一个问题。。
看了下代码,在win32下是用BOOL QueryPerformanceCounter( LARGE_INTEGER *lpFrequency );来计算当前时间的。猜测是这个函数在多核情况下不准确。

整理简洁后的代码流程大致如下:
ACE_OS::gethrtime (const ACE_HRTimer_Op op)
{
  ACE_UNUSED_ARG(op);
  LARGE_INTEGER freq;

  ::QueryPerformanceCounter (&freq);
  return freq.QuadPart;
}

ACE_INLINE void
ACE_High_Res_Timer::hrtime_to_tv (ACE_Time_Value &tv,
                                  const ACE_hrtime_t hrt)
{
  tv.sec ((long) (hrt / 1000000 ));

ACE_hrtime_t tmp = tv.sec ();
  tmp *= (1000000 );
  tv.usec ((long) (hrt - tmp));
}

ACE_INLINE ACE_Time_Value
ACE_High_Res_Timer::gettimeofday (const ACE_OS::ACE_HRTimer_Op op)
{
  ACE_Time_Value tv;
  ACE_High_Res_Timer::hrtime_to_tv (tv, ACE_OS::gethrtime (op));
  return tv;
}

[ 本帖最后由 wishel 于 2009-12-31 17:04 编辑 ]
您需要登录后才可以回帖 登录 | 用户注册

本版积分规则

Archiver|手机版|小黑屋|ACE Developer ( 京ICP备06055248号 )

GMT+8, 2024-11-22 13:13 , Processed in 0.017907 second(s), 5 queries , Redis On.

Powered by Discuz! X3.5

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表