c-使用clock_gettime(clock_MONOTONIC)测量运行时间



在多个线程中,我必须经过测量时间。我必须得到这样的输出:

Starting Time | Thread Number
00000000000   |   1
00000000100   |   2
00000000200   |   3

首先,我使用了gettimeofday,但我发现有一些负数,然后我做了一些研究,了解到gettimeofday不能可靠地测量经过的时间。然后我决定使用clock_gettime(clock_MONOTONIC(。

然而,存在一个问题。当我用秒来测量时间时,我无法精确地测量时间。当我使用纳秒时,end.tv_nsec变量的长度不能超过9位(因为它是一个长变量(。这意味着,当它必须移动到第10位时,它仍然保持在9位,实际上这个数字变小了,导致经过的时间为负数。

这是我的代码:

long elapsedTime;
struct timespec end;
struct timespec start2;
//gettimeofday(&start2, NULL);
clock_gettime(CLOCK_MONOTONIC,&start2);
while(c <= totalCount)
{   
if(strcmp(algorithm,"FCFS") == 0)
{
printf("In SErunner count=%d n",count);
if(count > 0)
{
printf("Count = %d n",count);

it = deQueue();
c++;
tid = it->tid;
clock_gettime(CLOCK_MONOTONIC,&end);

usleep( 1000*(it->value));
elapsedTime = ( end.tv_sec - start2.tv_sec);

printf("Process of thread %d finished with value %dn",it->tid,it->value);
fprintf(outputFile,"%ld %d %dn",elapsedTime,it->value,it->tid+1);
}
}

遗憾的是,timespec没有微秒变量。如果你能帮助我,我会很高兴的。

编写一个助手函数,用于计算两个时间段之间的差异:

int64_t difftimespec_ns(const struct timespec after, const struct timespec before)
{
return ((int64_t)after.tv_sec - (int64_t)before.tv_sec) * (int64_t)1000000000
+ ((int64_t)after.tv_nsec - (int64_t)before.tv_nsec);
}

如果你想要以微秒为单位,只需将其除以1000,或者使用:

int64_t difftimespec_us(const struct timespec after, const struct timespec before)
{
return ((int64_t)after.tv_sec - (int64_t)before.tv_sec) * (int64_t)1000000
+ ((int64_t)after.tv_nsec - (int64_t)before.tv_nsec) / 1000;
}

请记住包含<inttypes.h>,以便您可以使用转换"%" PRIi64打印int64_t类型的整数:

printf("%09" PRIi64 " | 5n", difftimespec_ns(after, before));

要计算delta(运行时间(,您需要根据使用的服务在两个timeval或两个timespec结构之间创建一个子动作。

对于timeval,有一组操作来操作<sys/time.h>(例如/usr/include/x86_64-linux-gnu/sys/time.h(:

# define timersub(a, b, result)                        
do {                                                 
(result)->tv_sec = (a)->tv_sec - (b)->tv_sec;      
(result)->tv_usec = (a)->tv_usec - (b)->tv_usec;   
if ((result)->tv_usec < 0) {                       
--(result)->tv_sec;                              
(result)->tv_usec += 1000000;                    
}                                                  
} while (0)

对于timespec,如果您的头文件中没有安装它们,请复制类似于此源代码中定义的宏的内容:

#define timespecsub(tsp, usp, vsp)                          
do {                                                    
(vsp)->tv_sec = (tsp)->tv_sec - (usp)->tv_sec;      
(vsp)->tv_nsec = (tsp)->tv_nsec - (usp)->tv_nsec;   
if ((vsp)->tv_nsec < 0) {                           
(vsp)->tv_sec--;                                
(vsp)->tv_nsec += 1000000000L;                  
}                                                   
} while (0)

您可以使用以下代码将时间转换为double值:

double
clocktime_BM (clockid_t clid)
{
struct timespec ts = { 0, 0 };
if (clock_gettime (clid, &ts))
return NAN;
return (double) ts.tv_sec + 1.0e-9 * ts.tv_nsec;
}    

返回的double值包含以秒为单位的内容。在大多数机器上,double-s是IEEE 754浮点数,对它们的基本运算速度很快(每个不到1µs(。阅读floating-point-gui.de了解更多关于它们的信息。2020年,基于x86-64的笔记本电脑和服务器具有一些HPET。不要指望时间测量的精度是微秒(因为Linux运行许多进程,它们可能会在任意时间被调度;请阅读一些关于操作系统的好教材进行解释(。

(以上代码来自Bismon,由CHARIOT资助;RefPerSys中也出现了类似的内容(

在Linux上,请确保读取syscalls(2(、clock_gettime(2(,errno(3(、time(7(和vdso(7(。

考虑研究Linux内核和/或GNU libc和/或musl-libc的源代码。请参阅LinuxFromScratch和OSDEV以及内核新手。

请注意某些32位计算机上的2038年问题。

相关内容

  • 没有找到相关文章

最新更新