如何在运行时使用 POSIX Clock() 函数监控 CPU 利用率?
有没有可靠的方法可以测量程序在运行时的 CPU 利用率?
我可能必须使用 time.h。这个想法是首先使用一些毫秒来设置空闲CPU负载(步骤A),然后设置满CPU负载(步骤B),然后启动程序并不断调用clock()。因此,我可以计算相对于步骤 A 和步骤 B 计算的 CPU 利用率,以百分比形式监控 CPU 利用率。我假设所有其他后台进程都被忽略。
但是,我不确定,如何仅使用 C89 和 POSIX 正确实现这些步骤 A 和步骤 B,例如idle() 和 full_load() 函数?
Is there any reliable method how a program can measure its CPU utilization during its runtime?
I probably have to use a POSIX clock() function from time.h. The idea is first to use some milliseconds to set an idle CPU load (step A), then full CPU load (step B), then to start a program and call clock() constantly. Thus, I can calculate CPU utilization relative to a calculated on step A and step B to monitor a CPU utilization in the percentage. I assume that all other background processes are ignored.
However, I am not sure, how to implement these step A and step B, say idle() and full_load() functions properly using only C89 and POSIX?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
当您说“full_load”时,并且您只需要一个负载下的 CPU 或虚拟核心,一个简单的紧密循环就可以解决问题。当然,它不会使用芯片上的所有晶体管(即,我们不是在谈论“满载”的老化测试),但它会在 CPU 获得的预定时间片内使用,使用所有可用的时钟周期,没有系统调用,这会放弃对内核的控制,并可能导致稍后重新调度执行线程。您还可以使用带有信号处理程序的警报来退出循环。这样您就可以运行循环大约一秒的执行时间(警报的时间并不完全准确……它们很接近,但没有达到时钟周期)。
此外,对于“空闲”负载部分,您可以执行相同的操作,但使用
sigsuspend()
而不是紧密循环,这将等待警报响起。因此,您的代码可能如下所示:
请记住,根据 POSIX 标准,每秒应该有 100 万个时钟作为
clock_t
值的时基,因此您应该看到为“full_load”返回的数字接近该数字,因为我们将“满载”大约一秒钟。空载负载应该很小(当然)。以下是我在 Mac Pro 上生成的数字:因此,就了解您可能会看到从
clock()
返回的时钟周期而言,这似乎与您正在寻找的内容有些一致。当然,我会多次运行此操作并取平均值,以便更好地指示您可能会看到的差异。When you say "full_load", and you only need a single CPU or virtual core under load, a simple tight loop will do the trick. Granted, it won't use all the transistors on the chip (i.e., we're not talking about a burn-in test for "full-load"), but it will, for the scheduled time-slice it gets of the CPU, use all the available clock-cycles with no syscalls that would give up control to the kernel and possibly cause the executing thread to be re-scheduled for later. Also you could use an alarm with a signal handler in order to exit from the loop. So that would let you run the loop for approximately a second of execution time (alarms aren't exactly time-accurate ... they're close, but not down to the clock-cycle).
In addition, for the "idle" load portion, you could do the same thing, but using a
sigsuspend()
instead of a tight loop, that would wait for the alarm to go off.So your code could look something like the following:
Keep in mind that according to the POSIX standard, there should be 1 million clocks per second as the time-base for the the
clock_t
value, so you should see the number returned for the "full_load" that is close to that number since we're going "full-load" for approximately a second. Idle load should be very small (of course). Here's numbers I generated on my Mac Pro:So that seems somewhat in-line with what you're looking for as far as knowing how many clock cycles you may see returned from
clock()
. I would of course run this multiple times and take an average to get a better indicator of the variance you might see.我认为这是由 CLOCK_VIRTUAL (BSD/HP-UX) 或 Linux 上的 CLOCK_PROCESS_CPUTIME_ID 覆盖的 Clock_gettime(2) 。
I thought this is covered by CLOCK_VIRTUAL (BSD/HP-UX) or CLOCK_PROCESS_CPUTIME_ID on linux for clock_gettime(2).
您没有指定 POSIX 的版本,但如果您使用的是 C89,它一定很旧。 POSIX.1-2001 又名 SUSv3 需要 C99,还有 POSIX.1-2008。
校准似乎没有必要;只需将返回的值与单调时间(更好,但可能不可用)或挂钟时间进行比较。对于
clock()
,使用CLOCKS_PER_SEC
定义(如果系统支持XSI选项,则保证为一百万,但如果系统仅支持POSIX则不然)。考虑使用
getrusage()
而不是clock()
以获得更高的准确性和灵活性。在早期的 POSIX 版本中,函数
getrusage()
位于 XSI 选项下;更改历史显示它是在第 4 版版本 2 (SUSv1) 中引入的,并在第 5 版 (SUSv2) 中移至基础,但其上仍然有 XSI 标记。无论如何,它很常见,因为它是 4.2BSD 的函数。另一个选项是 times() 函数。
You do not specify the version of POSIX, but if you are using C89, it must be pretty old. POSIX.1-2001 aka SUSv3 requires C99 and there is also POSIX.1-2008.
Calibration seems unnecessary; just compare the values returned to monotonic (better, but may not be available) or wall clock time. For
clock()
, use theCLOCKS_PER_SEC
define (this is guaranteed to be one million if the system supports the XSI option, but not if it is just POSIX).Consider
getrusage()
instead ofclock()
for more accuracy and flexibility.The function
getrusage()
was under the XSI option in earlier POSIX versions; the change history says it was introduced in Issue 4 Version 2 (SUSv1) and was moved to the base in Issue 5 (SUSv2) but there are still XSI markings on it. In any case it is pretty common as it is a 4.2BSD function.Another option is the
times()
function.