,所以我试图知道到目前为止的当前线程已经执行的时间。我正在尝试使用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个纳米的东西)。