首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >用户CPU时间和系统CPU时间在地理信息系统(RUSAGE_THREAD,&r_usage)中是如何精确测量的?

用户CPU时间和系统CPU时间在地理信息系统(RUSAGE_THREAD,&r_usage)中是如何精确测量的?
EN

Stack Overflow用户
提问于 2017-02-17 16:18:30
回答 2查看 1.7K关注 0票数 2

因此,我试图知道当前线程执行到目前为止的时间。我正在尝试使用getrusage(RUSAGE_THREAD, &r_usage);来实现它。以下是我的困惑:

1-此函数返回的时间是否包括线程被阻塞(例如在条件变量上)或计划退出的时间?

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

3-我能提高时间精度使getrusage(RUSAGE_THREAD, &r_usage);在纳秒内返回吗?

非常感谢!

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2017-02-17 17:40:21

不,通常不会将阻塞的时间分配给用户或内核CPU时间(这是资源占用量)。rusage定时器基本上是一个由操作系统启动和停止的“挂钟定时器”:当进程被调度时,它会记录时间,当它被解压时,它会停止它(用户/内核在进入/退出内核例程时的分裂类似)。所有这些段的和是CPU时间。

在某些情况下,比如IO,内核可能正在执行真正的工作,而不是等待,这可能被分配给您的进程。

如果您想要更高的宝贵CPU时间,您应该查看性能计数器。在Linux上,您可以使用perf_events系统以虚拟化的方式访问这些计数器,也可以使用包装对该子系统访问的帕皮之类的库,或者最容易开始使用一些轻量级的工具,比如libpfc,它提供了直接的计数器访问。

你还会问:

此外,我如何包括在I/O上花费的时间?

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

或者,您可以尝试在应用程序级别测试IO调用。最后,您可以使用类似于ptrace或Linux上较新的FTrace来在内核级别检测IO调用,并且您可能可以通过进程对其进行过滤。较新的内核显然有“每个进程的IO会计”,但我不能很快找到一个好的链接。不过,iotop的源代码可能会有您需要的电话。

最后,这取决于到目前为止执行当前线程所指的时间:如果您想包含IO,那么您可能只想要线程启动后的挂钟时间?然后您可以使用clock_gettime和朋友,它们提供纳秒分辨率(名义上,但调用本身至少需要十几纳秒,所以您不会精确地测量需要1或2纳诺的东西)。

票数 2
EN

Stack Overflow用户

发布于 2017-02-17 17:17:51

似乎很难相信用掉的时间(不管出于什么原因)会被记为执行的时间--但在偶然的情况下,让我们做一个简单的实验来得到一个想法:

代码语言:javascript
复制
#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";
}

结果:

代码语言:javascript
复制
0.000000 [0.000000]
0.000000 [0.000000]

所以睡觉的时间是不收费的。我们可以对互斥进行类似的测试:

代码语言:javascript
复制
#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总是与互斥体相关联,它是您真正等待的互斥)。

尝试测试每一种可能的I/O是不太实际的,但过去的经验表明,同样的情况也是如此:等待I/O的时间被阻塞,不被视为执行时间。

就精度而言,我认为理论上可以提高到纳秒级的精度,但这将涉及重写内核,而不仅仅是翻转开关或调用不同的函数。现实地说,这是一个很大的疑问,你是否能够得到更多的准确性,即使那时。如果你需要纳秒级的精度,这可能不是合适的工具。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/42302622

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档