使用 wait4 与 cpuacct cgroup 进行 CPU 时间测量

使用 wait4 与 cpuacct cgroup 进行 CPU 时间测量

我想启动一个进程并测量它终止之前所需的CPU时间(用户+系统)。

我知道我可以使用wait4系统调用,它返回一个包含用户和系统时间的结构(我使用两个时间的总和)。

我也可以使用cpuacctcgroup 子系统,将进程放入一个新的cgroup中,并读取cpuacct.usage文件(其中包含用户和系统时间的组合)。

我知道前者在进程产生子进程时会出现问题(有时它们的时间不被计算在内)。然而,我认为对于单进程情况,两个测量值应该几乎相等。我预计 cpuacct 值会小一点,因为我只能在创建进程后将其放入 cgroup(但我在 fork 后立即执行此操作,因此差异应该很小)。

现在,对于需要几秒钟的过程,我看到了预期的结果。

例子:

wait4:   8.292518s
cpuacct: 8.299105444s

wait4:   13.788861s
cpuacct: 13.796484557s

wait4:   24.229514s
cpuacct: 24.234132965s

wait4:   84.101255s
cpuacct: 84.104336222s

然而,对于需要更长时间的过程,我得到不同的结果:

wait4:   155.309706s
cpuacct: 155.306291274s

wait4:   505.547594s
cpuacct: 505.526723631s

wait4:   897.180069s
cpuacct: 897.131232685s

现在 cpuacct 值有点低,这是我从未预料到的。有人知道为什么会发生这种情况吗?

我不在乎0.1s的精度,而且我从未经历过更高的差异。我可以确信差异总是那么小吗?或者是否有可能出现差异更大的情况?

文档cpuacct指出该值在两种情况下可能不精确。但是,这两种情况都不适用,因为我在 64 位机器上,并且我可以在进程完成后等待任意时间,读取的cpuacct.usage值将保持不变(所以我坚信它不是一个过时的值)。

精确设置:
我的启动进程是一个Python进程。我习惯于subprocess.Popen()产生任务并os.wait4()获得时间。为了使用 cgroup,我将一个函数传递给将新进程添加到 cgrouppreexec_fn的参数(因此这是在和系统调用之间完成的)。启动的进程是一个Java VM。我认为这不相关,但我想提供此信息以防万一。Popenforkexec

相关内容