C++ 使用rusage的进程/线程不可能的Cpu时间
我正在计算进程/线程正在使用的cpu时间与调用某个函数之间的增量 我得到了进程cpu时间的不可能值,下一次调用返回的cpu时间更小,这是不可能的 这是我用来计算cpu时间的代码:C++ 使用rusage的进程/线程不可能的Cpu时间,c++,c,linux,multithreading,ace,C++,C,Linux,Multithreading,Ace,我正在计算进程/线程正在使用的cpu时间与调用某个函数之间的增量 我得到了进程cpu时间的不可能值,下一次调用返回的cpu时间更小,这是不可能的 这是我用来计算cpu时间的代码: u64 CpuTime::calculateCpuTime(bool a_thread) { struct rusage l_rusage; int retVal; if(a_thread) { retVal = getrusage(1, &l_rusage)
u64 CpuTime::calculateCpuTime(bool a_thread)
{
struct rusage l_rusage;
int retVal;
if(a_thread)
{
retVal = getrusage(1, &l_rusage); //1 = RUSAGE_THREAD
}
else
{
retVal = getrusage(0, &l_rusage); //0 = RUSAGE_SELF
}
ASSERT(retVal==0);
u64 userUSeconds = (static_cast<u64>(l_rusage.ru_utime.tv_sec)*1000000)+
(static_cast<u64>(l_rusage.ru_utime.tv_usec));
u64 systemUSeconds = (static_cast<u64>(l_rusage.ru_stime.tv_sec)*1000000)+
(static_cast<u64>(l_rusage.ru_stime.tv_usec));
if(a_thread)
{
return userUSeconds + systemUSeconds;
}
return (userUSeconds + systemUSeconds) / ACE_OS::num_processors_online();
}
执行系统调用的对象(“m_cpuTime”)是一个受互斥体保护的单线程,一次只能有一个线程访问它
它保存线程cpu使用情况的映射m_threadsCpuMap(用于增量),以及最后一个进程cpu使用情况m_processCpu
另一编辑:
我用一个简单的测试简化了它,使用一个线程,去掉了活动cpu的除法,并且只检查进程cpu时间,仍然有不可能的结果
以下是更新后的功能:
测试:
我使用ACE_OS实现可移植性,但它可以与sys/time.h中的默认函数一起工作
但是,我仍然对rusage奇怪的行为有疑问,是什么导致它给出这些值。仔细检查以下几行:您将系统时间秒乘以10万,而不是100万:
u64 userUSeconds = (static_cast<u64>(l_rusage.ru_utime.tv_sec)*1000000)+
(static_cast<u64>(l_rusage.ru_utime.tv_usec));
u64 systemUSeconds = (static_cast<u64>(l_rusage.ru_stime.tv_sec)*100000)+
(static_cast<u64>(l_rusage.ru_stime.tv_usec));
也就是-900000(0.9秒)+1000 us我注意到,在系统时间计算中,您没有应用相同的数学来计算用户和系统时间(缺少*100000)。我将添加其余部分,希望将其缩短一点。关于*1000000,r_使用时间以秒为单位,r_时间以微秒为单位,当我以微秒为单位返回值时,我只需要乘以秒数,收集4个不同的值,同时获取/释放锁可能是问题的根源,任何线程都可能启动并延迟当前线程的执行。这对你来说可能是个问题,也可能不是问题,一旦你收集了这些值,我就没有深入了解你在做什么:-如果你没有向我们展示真正的代码,有点难以帮助你,哈哈。你的map m_threadsCpuMap对象是什么类型的。我看到您获得了对其中值的引用,并假设它是映射中的实际值,因此当它得到更新时,您不需要在映射中重新设置值。。这是一个有效的假设吗?它可能会将副本返回给您,而您正在引用/更新副本而不是原始副本?或者它是一个简单的数组:)?谢谢你,不敢相信我真的错过了,它总是最简单的错误。
u64 CpuTime::getThreadDeltaCpuTime()
{
pid_t thisThread = (pid_t) syscall (SYS_gettid);
u64& val = m_threadsCpuMap[thisThread];
u64 oldValue =val;
val = calculateCpuTime(true);
return val - oldValue;
}
u64 CpuTime::getProcessDeltaCpuTime()
{
u64 oldValue = m_processCpu;
m_processCpu = calculateCpuTime(false);
return m_processCpu - oldValue;
}
u64 getThreadCpuTime()
{
return CpuTime::calculateCpuTime(true);
}
u64 getProcessCpuTime()
{
return CpuTime::calculateCpuTime(false);
}
for(int i = 0; i < 100000 ; i++)
{
for(int k = 0; k < 1000000; k++)
m = k % i;
cpuTime = CpuTime::instance()->getProcessDeltaCpuTime();
}
u64 CpuTime::getProcessDeltaCpuTime()
{
u64 oldValue = m_processCpu;
m_processCpu = calculateCpuTime(eThisProcess);
Log<<value(oldValue)<<value(m_processCpu)<value( m_processCpu - oldValue)<<endlog;
return m_processCpu - oldValue;
}
u64 CpuTime::calculateCpuTime(int a_type)
{
struct rusage l_rusage;
int retVal;
if(a_type == eThisThread)
{
retVal = /*ACE_OS::*/getrusage(1, &l_rusage);
}
else
{
retVal = /*ACE_OS::*/getrusage(0, &l_rusage);
}
u64 userUSeconds = (static_cast<u64>(l_rusage.ru_utime.tv_sec)*1000000)+
(static_cast<u64>(l_rusage.ru_utime.tv_usec));
u64 systemUSeconds = (static_cast<u64>(l_rusage.ru_stime.tv_sec)*100000)+
(static_cast<u64>(l_rusage.ru_stime.tv_usec));
if(a_type == eThisThread)
{
return userUSeconds + systemUSeconds;
}
return (userUSeconds + systemUSeconds)/* / ACE_OS::num_processors_online()*/;
int main()
{
long int n = 0;
long int oldValue = 0;
long int newValue = 0;
unsigned long int deltaValue = 0;
for(int i = 0; i < 1000000; i++)
{
for(long int m = 0; m <10000; m++)
n = m + i;
struct rusage l_rusage;
int retVal;
retVal = getrusage(0, &l_rusage);
if(retVal != 0) return 0;
long int userUSeconds = l_rusage.ru_utime.tv_sec*1000000 + l_rusage.ru_utime.tv_usec;
long int systemUSeconds = l_rusage.ru_stime.tv_sec*100000 + l_rusage.ru_stime.tv_usec;
oldValue = newValue;
newValue = userUSeconds + systemUSeconds;
deltaValue = newValue - oldValue;
if(deltaValue != 0)
std::cout<<"Old value: "<< oldValue <<" New Value: "<< newValue <<" Delta value: "<<deltaValue<<"\n";
}
std::cout<<n;
return 0;
}
u64 CpuMeasure::calculateCpuTime(int a_type)
{
struct timespec ts;
if(a_type == eThisThread)
{
if (ACE_OS::clock_gettime(CLOCK_THREAD_CPUTIME_ID, &ts) == 0)
{
return (u64)ts.tv_sec * 1000000 + (u64)ts.tv_nsec / 1000; //From nano to mili seconds
}
}
else
{
if (ACE_OS::clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &ts) == 0)
{
return (u64)ts.tv_sec * 1000000 + (u64)ts.tv_nsec / 1000;
}
}
ASSERT(false); //we cant be here, unless some thing bad happened
return 0;
}
u64 userUSeconds = (static_cast<u64>(l_rusage.ru_utime.tv_sec)*1000000)+
(static_cast<u64>(l_rusage.ru_utime.tv_usec));
u64 systemUSeconds = (static_cast<u64>(l_rusage.ru_stime.tv_sec)*100000)+
(static_cast<u64>(l_rusage.ru_stime.tv_usec));
18446744073708652615 - 2^64 + 1 = -899000