使用 clock_gettime(CLOCK_MONOTONIC) 测量经过的时间
Measuring Elapsed Time Using 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 %d\n",it->tid,it->value);
fprintf(outputFile,"%ld %d %d\n",elapsedTime,it->value,it->tid+1);
}
}
不幸的是,timespec 没有微秒变量。如果你能帮助我,我会很高兴。
要计算增量(经过的时间),您需要在两个 timeval 或两个 timespec 结构之间进行减法,具体取决于您正在使用的服务。
对于timeval,有一组操作在struct timeval .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,如果您没有在您的头文件中安装它们,请复制类似于此 source code:
中定义的宏的内容
#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)
编写一个辅助函数来计算两个时间规格之间的差异:
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;
}
记得包含 ,这样您就可以使用转换 "%" PRIi64
来打印 int64_t
类型的整数:
printf("%09" PRIi64 " | 5\n", difftimespec_ns(after, before));
您可以使用一些代码将时间转换为 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 floating point numbers, and basic operations on them are fast (less than a µs each). Read the floating-point-gui.de for more about them. In 2020 x86-64 based laptops and servers have some HPET. Don't expect a microsecond precision on time measurements (since Linux runs many processes, and they might get scheduled at arbitrary times; read some good textbook about operating systems 用于解释)。
(以上代码来自Bismon, funded thru CHARIOT; something similar appears in RefPerSys)
在 Linux 上,请务必阅读 syscalls(2), clock_gettime(2), errno(3), time(7), vdso(7)。
考虑研究 Linux kernel and/or of the GNU libc and/or of musl-libc. See LinuxFromScratch and OSDEV and kernelnewbies.
的源代码
注意 一些 32 位计算机上的 The year 2038 problem。
我必须在多个线程中消耗测量时间。我必须得到这样的输出:
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 %d\n",it->tid,it->value);
fprintf(outputFile,"%ld %d %d\n",elapsedTime,it->value,it->tid+1);
}
}
不幸的是,timespec 没有微秒变量。如果你能帮助我,我会很高兴。
要计算增量(经过的时间),您需要在两个 timeval 或两个 timespec 结构之间进行减法,具体取决于您正在使用的服务。
对于timeval,有一组操作在
# 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,如果您没有在您的头文件中安装它们,请复制类似于此 source code:
中定义的宏的内容#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)
编写一个辅助函数来计算两个时间规格之间的差异:
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;
}
记得包含 "%" PRIi64
来打印 int64_t
类型的整数:
printf("%09" PRIi64 " | 5\n", difftimespec_ns(after, before));
您可以使用一些代码将时间转换为 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 floating point numbers, and basic operations on them are fast (less than a µs each). Read the floating-point-gui.de for more about them. In 2020 x86-64 based laptops and servers have some HPET. Don't expect a microsecond precision on time measurements (since Linux runs many processes, and they might get scheduled at arbitrary times; read some good textbook about operating systems 用于解释)。
(以上代码来自Bismon, funded thru CHARIOT; something similar appears in RefPerSys)
在 Linux 上,请务必阅读 syscalls(2), clock_gettime(2), errno(3), time(7), vdso(7)。
考虑研究 Linux kernel and/or of the GNU libc and/or of musl-libc. See LinuxFromScratch and OSDEV and kernelnewbies.
的源代码注意 一些 32 位计算机上的 The year 2038 problem。