c语言 - 用户 CPU 时间和系统 CPU 时间在 getrusage(RUSAGE_THREAD, &r_usage) 中准确测量什么?



,所以我试图知道到目前为止的当前线程已经执行的时间。我正在尝试使用getrusage(RUSAGE_THREAD, &r_usage);。这是我的困惑:

1-此功能返回的时间是否包括被阻止的线程(例如,在条件变量上)或计划出来的时间?

2-由于其他原因,该线程被阻止的时间如何,例如为I/O?

阻止

3-我可以增加使getrusage(RUSAGE_THREAD, &r_usage);返回纳秒的时间准确性吗?

非常感谢!

似乎很难相信(无论出于何种原因,花费的时间都会被收取),因为执行的时间是在遇到的机会,但让我们快速进行实验以获取一个想法:

#include <unistd.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <iostream>
#include <iomanip>
std::ostream &operator<<(std::ostream &os, timeval const &t) {
    return os << t.tv_sec << '.' << std::setw(6) << std::setfill('0') << t.tv_usec << std::setfill(' ');
}
int main() {
    rusage r;
    getrusage(RUSAGE_THREAD, &r);
    std::cout << r.ru_utime << " [" << r.ru_stime << "]n";
    sleep(10);
    getrusage(RUSAGE_THREAD, &r);
    std::cout << r.ru_utime << " [" << r.ru_stime << "]n";
}

结果:

0.000000 [0.000000]
0.000000 [0.000000]

因此,睡觉的时间没有收费。我们可以使用静音:

进行类似的测试
#include <sys/time.h>
#include <sys/resource.h>
#include <iostream>
#include <iomanip>
#include <thread>
#include <mutex>
using namespace std::literals;
std::ostream &operator<<(std::ostream &os, timeval const &t) {
    return os << t.tv_sec << '.' << std::setw(6) << std::setfill('0') << t.tv_usec << std::setfill(' ');
}
int main() {
    rusage r;
    getrusage(RUSAGE_THREAD, &r);
    std::cout << r.ru_utime << " [" << r.ru_stime << "]n" << std::flush;
    std::mutex m;
    m.try_lock();   // ensure mutex is locked
    // create thread to unlock mutex after 5 seconds:
    auto t = std::thread([&]{ std::this_thread::sleep_for(5s); m.unlock(); });
    // wait for mutex to be unlocked
    m.lock();
    // re-check resource usage
    getrusage(RUSAGE_THREAD, &r);
    std::cout << r.ru_utime << " [" << r.ru_stime << "]n";
    t.join();
}

这给出了类似的结果。我没有为条件变量重复重复它,但是看到它的不同结果会感到非常惊讶(Condvar始终与Mutex相关联,而这是您真正等待的Mutex)。

>

尝试测试每种可能的I/O,但过去的经验表明,与之相同:等待I/O的时间不被视为执行时间。

就准确性而言,我想您可以从理论上提高纳秒范围的准确性,但它将涉及重写内核,而不仅仅是翻转开关或调用其他功能。实际上,即使您能够更加准确,这对您是否能够更加准确。如果您需要纳秒级的精度,这可能不是工作的正确工具。

no,通常不会将阻塞时间分配给用户或内核CPU时间(这是rusage措施的方法)。rusage计时器基本上是一个由OS启动和停止的"壁时钟计时器":当计划安排时,它注意了时间,当它被取消时,它会停止它(类似地适用于在入口/Exit上的用户/内核拆分到内核例程)。所有这些段的总和是CPU时间。

在某些情况下,例如IO,内核可能正在做真正的工作,而不是等待,并且可能会分配给您的流程。

如果您想为 cpu Time 提高珍贵,则应研究性能计数器。在Linux上,您可以使用perf_events系统以虚拟化的方式访问这些计数器,或者使用包装对该子系统访问的Papi之类的库,或者最容易开始使用的是使用LibPFC这样的轻巧的东西,例如Libpfc,它提供了直接的计数器访问。<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

您也问:

此外,我如何包括在I/O?

上花费的时间

这是一个棘手的问题,因为现代系统中IO的异步和缓存性质。很难确切地确定所花费的时间以及如何分配它(例如,如果一个过程将页面从磁盘带到缓存中,但是随后有10个其他过程随后访问它,您如何将IO时间分配给IO时间)?人们认为您可以做的就是查看可能在IO指示器上具有阻塞的/proc/pid/计数器和状态条目。实际上,top可以在此状态下显示进程,因此您可能会从/proc/$pid中获取此过程。请注意,我认为您必须从其他线程中对该文件系统进行采样,以使该文件进行工作。

另外,您可以尝试在应用级别的io呼叫上进行仪器。最后,您可以在IO调用的内核级别使用ptrace或Linux上的较新的FTrace来进行仪器,并且您可能可以按进程过滤。较新的内核显然具有"人均IO会计" - 但我无法迅速挖掘一个好的链接。 iotop的来源可能会带有您需要的电话。

最后,这完全取决于您的含义当前线程到目前为止执行的时间:如果您想包括IO线程开始?然后,您可以使用clock_gettime和朋友,它们提供纳秒分辨率(名义上是,但通话本身至少需要十二纳秒,因此您不会准确地测量需要1或2个纳米的东西)。

最新更新