1. 進程運行時間的概念
如何度量進程的運行時間?
可以用times函數獲取進程的牆上時鍾時間,用戶CPU時間,系統CPU時鍾時間。
1.1 牆上時鍾時間
牆上時鍾時間 wall clock time: 又簡稱時鍾時間,從進程開始運行到結束,系統時鍾走過的時間(時鍾數),包含了進程阻塞、等待的時間。
每秒鍾嘀嗒數, 可通過sysconf(_SC_CLK_TCK)
獲取
注意: 如果調用clock()計算進程/算法運行時間, 是不包括阻塞(含sleep)時間的.
1.2 用戶CPU時間
用戶CPU時間:用戶進程在用戶態執行時間。
1.3 系統CPU時間
系統CPU時間:用戶進程在內核態執行時間。
1.4 三者之間關系
(牆上)時鍾時間 = 阻塞時間 + 就緒時間 + 運行時間
運行時間 = 用戶CPU時間 + 系統CPU時間
2. 如何獲取進程相關運行時間?
2.1 times函數
獲取進程時間
原型
#include <sys/times.h>
clock_t times(struct tms *buf);
tms結構:
struct tms {
clock_t tms_utime; /* user CPU time */
clock_t tms_stime; /* system CPU time */
clock_t tms_cutime; /* user CPU time,terminated children */
clock_t tms_cstime; /* system CPU time,terminated children */
};
功能
獲取當前進程牆上時鍾時間,用戶CPU時間,系統CPU時鍾時間
返回值
1.函數返回牆上時鍾時間。
進程開始和結束時,可以分別獲取到2個返回值,做差值即為進程的牆上時鍾時間。運行時間足夠長可能溢出(可能性較小)
2.輸出參數buf,包含用戶CPU時間,系統CPU時間。
2.2 getrusage 函數
獲取資源使用(統計情況).
getrusage 也可以用於獲取進程的用戶CPU時間, 系統CPU時間, 而且適用於多進程、多線程環境, 功能比times函數更強大.
#include <sys/time.h>
#include <sys/resource.h>
int getrusage(int who, struct rusage *usage);
- 參數
who 函數getrusage能返回何種資源使用測量值, 取決於who參數:
1)RUSAGE_SELF 返回調用進程所有線程的資源使用統計;
2)RUSAGE_CHILDREN 返回調用進程的所有已終止子進程的資源使用統計;
3)RUSAGE_THREAD 返回調用線程的資源使用統計, 不過要求_GNU_SOURCE已在<sys/resource.h>.中定義;
usage 指向rusage結構, 包含了用戶CPU時間, 系統CPU時間,
struct rusage {
struct timeval ru_utime; /* user CPU time used 使用了的用戶CPU時間 */
struct timeval ru_stime; /* system CPU time used 使用了的系統CPU時間 */
long ru_maxrss; /* maximum resident set size 最大占用物理內存大小(瞬時值, 單位KB) */
long ru_ixrss; /* integral shared memory size 完整的共享內存大小, linux未使用 */
long ru_idrss; /* integral unshared data size 完整的非共享數據大小, linux未使用 */
long ru_isrss; /* integral unshared stack size 完整的非共享棧大小, linux未使用 */
long ru_minflt; /* page reclaims (soft page faults) soft page faults次數: 需要訪問的內存不在虛擬地址空間,但是在物理內存, 需要MMU建立和物理內存的映射. 不需要IO活動 */
long ru_majflt; /* page faults (hard page faults) hard page faults次數: 需要訪問的內存不在虛擬地址空間,也不在物理內存中,需要從慢速設備載入. 需要IO活動 */
long ru_nswap; /* swaps linux未使用 */
long ru_inblock; /* block input operations 阻塞輸入操作次數 */
long ru_oublock; /* block output operations 阻塞輸出操作次數 */
long ru_msgsnd; /* IPC messages sent linux未使用 */
long ru_msgrcv; /* IPC messages received linux未使用 */
long ru_nsignals; /* signals received linux未使用 */
long ru_nvcsw; /* voluntary context switches 主動上下文切換(時間片用完)時間數 */
long ru_nivcsw; /* involuntary context switches 被動上下午切換(更高優先級進程搶占)時間數 */
};
2.3 getrusage例子
利用getrusage打印總的用戶CPU時間, 總的系統CPU時間.
void
pr_cpu_time(void)
{
double user, sys;
struct rusage myusage, childusage;
/* 調用進程資源利用統計 */
if (getrusage(RUSAGE_SELF, &myusage) < 0)
err_sys("getrusage error");
/* 調用進程已終止子進程資源利用統計 */
if (getrusage(RUSAGE_CHILDREN, &myusage) < 0)
err_sys("getrusage error");
user = (double) myusage.ru_utime.tv_sec + myusage.ru_utime.tv_usec / 1000000.0;
user = (double) childusage.ru_utime.tv_sec + childusage.ru_utime.tv_usec / 1000000.0;
sys = (double) myusage.ru_stime.tv_sec + myusage.ru_stime.tv_usec / 1000000.0;
sys = (double) childusage.ru_stime.tv_sec + childusage.ru_stime.tv_usec / 1000000.0;
/* 打印用戶CPU時間, 系統CPU時間. %g 根據結果自動選擇輸出格式%f, %e, 科學計數法 */
printf("user time = %g, sys time = %g\n", user, sys);
}