在多个线程中,我必须经过测量时间。我必须得到这样的输出:
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年问题。