如何在C语言中以毫秒为单位获取程序的执行时间?

10

目前我通过调用以下方法来获取我的程序的执行时间(以为单位):

time_t startTime = time(NULL);
//section of code
time_t endTime = time(NULL);
double duration = difftime(endTime, startTime);

是否可以以毫秒为单位获取墙上时间?如果可以,如何实现?


我不能将结果乘以1000。 - manugupt1
6个回答

9
如果您使用的是类POSIX操作系统,应该使用 gettimeofday() 函数,它具有合理的可移植性和微秒级别分辨率。
稍微有些鲜为人知,但同样在POSIX标准中的函数是 clock_gettime(),它可以提供纳秒级别的分辨率。
在许多系统上,您会找到一个名为 ftime() 的函数,它可以返回以秒和毫秒为单位的时间。然而,此函数已不再属于Single Unix规范(大致等同于POSIX)。您需要包含头文件 <sys/timeb.h>
struct timeb mt;
if (ftime(&mt) == 0)
{
     mt.time ... seconds
     mt.millitime ... milliseconds
}

这可以追溯到至少第七版Unix(或7版),因此已经非常广泛地可用。
我在我的亚秒计时器代码中还有关于times()和clock()的其他结构和头文件的注释。我还有关于Windows使用每秒1000个时钟滴答声(毫秒定时)的clock(),以及一个旧的接口GetTickCount()的注释,该接口被认为是Windows 95必需的,但在NT上不需要。

注意:gettimeofday()在POSIX 2008中被正式标记为“过时”。这并不意味着它很快就会消失,但预示着它的命运已经注定。 - Jonathan Leffler

3
我最近写了一篇博客,介绍了如何跨平台获取毫秒级时间
它的作用类似于time(NULL),但是在Windows和Linux上返回的是从Unix纪元以来的毫秒数,而不是秒数。

以下是代码

#ifdef WIN32
#include <Windows.h>
#else
#include <sys/time.h>
#include <ctime>
#endif

/* Returns the amount of milliseconds elapsed since the UNIX epoch. Works on both
 * windows and linux. */

int64 GetTimeMs64()
{
#ifdef WIN32
 /* Windows */
 FILETIME ft;
 LARGE_INTEGER li;
 uint64 ret;

 /* Get the amount of 100 nano seconds intervals elapsed since January 1, 1601 (UTC) and copy it
  * to a LARGE_INTEGER structure. */
 GetSystemTimeAsFileTime(&ft);
 li.LowPart = ft.dwLowDateTime;
 li.HighPart = ft.dwHighDateTime;

 ret = li.QuadPart;
 ret -= 116444736000000000LL; /* Convert from file time to UNIX epoch time. */
 ret /= 10000; /* From 100 nano seconds (10^-7) to 1 millisecond (10^-3) intervals */

 return ret;
#else
 /* Linux */
 struct timeval tv;
 uint64 ret;

 gettimeofday(&tv, NULL);

 ret = tv.tv_usec;
 /* Convert from micro seconds (10^-6) to milliseconds (10^-3) */
 ret /= 1000;

 /* Adds the seconds (10^0) after converting them to milliseconds (10^-3) */
 ret += (tv.tv_sec * 1000);

 return ret;
#endif
}

如果您想要,您可以将其修改为返回微秒而不是毫秒。


3
如果你想在Linux系统中,在程序之外操作,你可以使用time命令(time ./my_program)来实现。该命令可以计算出程序运行的时间。

谢谢,这非常有帮助。 - Games Brainiac
@poundifdef 赞同,但不理解用户时间和系统时间? - Mohan

0

gprof是GNU工具包的一部分,是一个选项。大多数POSIX系统都会安装它,并且在Windows下的Cygwin中也可以使用。使用gettimeofday()自己跟踪时间是可行的,但这相当于使用打印语句进行调试的性能等效方法。如果您只想要一个快速而简单的解决方案,那么这很好,但它不如使用适当的工具优雅。

要使用gprof,必须在使用gcc编译时指定-pg选项,如下所示:

gcc -o prg source.c -pg

然后您可以按照以下方式在生成的程序上运行gprof:
gprof prg > gprof.out

默认情况下,gprof将生成程序的总运行时间,以及每个函数中花费的时间,每个函数被调用的次数,每个函数调用中平均花费的时间等信息。

您可以使用大量选项设置gprof。如果您感兴趣,可以在man页面或通过Google获取更多信息。


0

开源GLib库具有GTimer系统,声称提供微秒级精度。该库可在Mac OS X、Windows和Linux上使用。我目前正在Linux上使用它来进行性能计时,它似乎完美地工作。


-3
在Windows上,使用QueryPerformanceCounter和相关的QueryPerformanceFrequency。它们不会给你一个可以转换为日历时间的时间,所以如果你需要这个,那么就使用CRT API请求时间,然后立即使用QueryPerformanceCounter。然后你可以进行一些简单的加减运算来计算日历时间,由于连续执行API所需的时间,可能会有一些误差。嘿,这是一台PC,你期望什么呢?

2
QueryPerformanceCounter在当前流行的CPU速度切换模式下无法正常工作。底层的PerformanceCounterFrequency变化非常迅速,只能用于小范围内的测量。 - Pavel Radzivilovsky
@Charlie,这太荒谬了。指出非实时操作系统无法准确测量事件的时间并不是一种攻击行为。 - David Gladfelter
@Pavel:您的评论与操作系统文档不一致,该文档说明性能计数器频率在运行中的操作系统上是恒定的。虽然曾经存在过导致您所描述行为的缺陷,但已进行了修补。请参见MSDN:http://msdn.microsoft.com/en-us/library/ms644905%28VS.85%29.aspx - David Gladfelter
@David:看过文档,很有趣。似乎有些英特尔CPU可以实现这一点,尽管速度开关(大多数HAL将调用转发到CPU指令以查询时钟计数器)。我不知道其他CPU如何实现这一点。 - Pavel Radzivilovsky

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接