
有一个简单方法,那就是定义一个装饰器来测量函数的执行时间,并输出结果:
import time
from functoolsimport wraps
import random
def fn_timer(function):
@wraps(function)
def function_timer(*args, **kwargs):
t0= time.time()
result= function(*args, **kwargs)
t1= time.time()
print("Total time running %s: %s seconds" %
(function.__name__, str(t1- t0))
)
return result
return function_timer
@fn_timer
def random_sort(n):
return sorted([random.random() for i in range(n)])
if __name__== "__main__":
random_sort(2000000)
输出:Total time running random_sort: 0.6598007678985596 seconds
使用方式的话,就是在要监控的函数定义上面加上 @fn_timer 就行了
或者
# 可监控程序运行时间
import time
import random
def clock(func):
def wrapper(*args, **kwargs):
start_time= time.time()
result= func(*args, **kwargs)
end_time= time.time()
print("共耗时: %s秒" % round(end_time- start_time, 5))
return result
return wrapper
@clock
def random_sort(n):
return sorted([random.random() for i in range(n)])
if __name__== "__main__":
random_sort(2000000)
输出结果:共耗时: 0.65634秒
2. 使用timeit模块
另一种方法是使用timeit模块,用来计算平均时间消耗。
执行下面的脚本可以运行该模块。
这里的timing_functions是Python脚本文件名称。
在输出的末尾,可以看到以下结果:4 loops, best of 5: 2.08 sec per loop
这表示测试了4次,平均每次测试重复5次,最好的测试结果是2.08秒。
如果不指定测试或重复次数,默认值为10次测试,每次重复5次。
3. 使用Unix系统中的time命令
然而,装饰器和timeit都是基于Python的。在外部环境测试Python时,unix time实用工具就非常有用。
运行time实用工具:
输出结果为:
Total time running random_sort: 1.3931210041 seconds
real 1.49
user 1.40
sys 0.08
第一行来自预定义的装饰器,其他三行为:
real表示的是执行脚本的总时间
user表示的是执行脚本消耗的CPU时间。
sys表示的是执行内核函数消耗的时间。
注意:根据维基百科的定义,内核是一个计算机程序,用来管理软件的输入输出,并将其翻译成CPU和其他计算机中的电子设备能够执行的数据处理指令。
因此,Real执行时间和User+Sys执行时间的差就是消耗在输入/输出和系统执行其他任务时消耗的时间。
4. 使用cProfile模块
5. 使用line_profiler模块
6. 使用memory_profiler模块
7. 使用guppy包
有4种方法可以达成测算程序运行时间的目的。它们分别是使用clock, times, gettimeofday, getrusage来实现的。
下面就来逐一介绍,并比较它们的优劣点。
系统测试环境:
VirtualBox (Ubuntu 9.10)
gcc version 4.4.1
libc6 2.10.1-0ubuntu16
Core Duo T2500 2GMHz
例程如下:
只要修改第11行的定义值,就可以使用不同的测量方法了。
#include <sys/time.h>
#include <sys/resource.h>
#include <unistd.h>
#include <stdio.h>
#include <time.h>
#define TEST_BY_CLOCK (char)(0x00)
#define TEST_BY_TIMES (char)(0x01)
#define TEST_BY_GETTIMEOFDAY(char)(0x02)
#define TEST_BY_GETRUSAGE (char)(0x03)
#define TEST_METHOD (TEST_BY_GETTIMEOFDAY)
#define COORDINATION_X (int)(1024)
#define COORDINATION_Y (int)(1024)
static int g_Matrix[COORDINATION_X][COORDINATION_Y]
double getTimeval()
{
struct rusage stRusage
struct timeval stTimeval
if (TEST_METHOD == TEST_BY_GETTIMEOFDAY)
{
gettimeofday(&stTimeval, NULL)
}
else if (TEST_METHOD == TEST_BY_GETRUSAGE)
{
getrusage(RUSAGE_SELF, &stRusage)
stTimeval = stRusage.ru_utime
}
return stTimeval.tv_sec + (double)stTimeval.tv_usec*1E-6
}
int main()
{
int i, j
int n = 0
clock_t clockT1, clockT2
double doubleT1, doubleT2
if (TEST_METHOD == TEST_BY_CLOCK)
{
clockT1 = clock()
}
else if (TEST_METHOD == TEST_BY_TIMES)
{
times(&clockT1)
}
else if (TEST_METHOD == TEST_BY_GETTIMEOFDAY)
{
doubleT1 = getTimeval()
}
else if (TEST_METHOD == TEST_BY_GETRUSAGE)
{
doubleT1 = getTimeval()
}
for (i = 0i <COORDINATION_Xi++)
{
for (j = 0j <COORDINATION_Yj++)
{
g_Matrix[i][j] = i * j
}
}
if (TEST_METHOD == TEST_BY_CLOCK)
{
clockT2 = clock()
printf("Time result tested by clock = %10.30f\n",(double)(clockT2 - clockT1)/CLOCKS_PER_SEC)
}
else if (TEST_METHOD == TEST_BY_TIMES)
{
times(&clockT2)
printf("Time result tested by times = %10.30f\n", (double)(clockT2 - clockT1)/sysconf(_SC_CLK_TCK))
}
else if (TEST_METHOD == TEST_BY_GETTIMEOFDAY)
{
doubleT2 = getTimeval()
printf("Time result tested by gettimeofday = %10.30f\n",(double)(doubleT2 - doubleT1))
}
else if (TEST_METHOD == TEST_BY_GETRUSAGE)
{
doubleT2 = getTimeval()
printf("Time result tested by getrusage = %10.70f\n", (double)(doubleT2 - doubleT1))
}
return 0
}
1. 使用clock的方法:
clock是ANSI C的标准库函数,关于这个函数需要说明几点。
首先,它返回的是CPU耗费在本程序上的时间。也就是说,途中sleep的话,由于CPU资源被释放,那段时间将不被计算在内。
其次,得到的返回值其实就是耗费在本程序上的CPU时间片的数量,也就是Clock Tick的值。该值必须除以CLOCKS_PER_SEC这个宏值,才
能最后得到ss.mmnn格式的运行时间。在POSIX兼容系统中,CLOCKS_PER_SEC的值为1,000,000的,也就是
1MHz。
最后,使用这个函数能达到的精度大约为10ms。
2. 使用times的方法:
times的用法基本和clock类似,同样是取得CPU时间片的数量,所不同的是要除以的时间单位值为sysconf(_SC_CLK_TCK)。
3. 使用gettimeofday的方法:
用gettimeofday直接提取硬件时钟进行运算,得到的结果的精度相比前两种方法提高了很多。
但是也正由于它提取硬件时钟的原因,这个方法只能计算程序开始时间和结束时间的差值。而此时系统中如果在运行其他的后台程序,可能会影响到最终结果的值。如果后台繁忙,系统dispatch过多的话,并不能完全真实反映被测量函数的运行时间。
4. 使用getrusage的方法:
getrusage得到的是程序对系统资源的占用信息。只要指定了RUSAGE_SELF,就可以得到程序本身运行所占用的系统时间。
Include head file time.h, though it's a C include file, C++ certainly can use it.Under C++, you can include <ctime>instead of <time.h>
_____________________________________________________
time.h
@函数名称: localtime
函数原型: struct tm *localtime(const time_t *timer)
函数功能: 返回一个以tm结构表达的机器时间信息
函数返回: 以tm结构表达的时间,结构tm定义如下:
struct tm{
int tm_sec
int tm_min
int tm_hour
int tm_mday
int tm_mon
int tm_year
int tm_wday
int tm_yday
int tm_isdst
}
参数说明: timer-使用time()函数获得的机器时间
所属文件: <time.h>
#include <time.h>
#include <stdio.h>
#include <dos.h>
int main()
{
time_t timer
struct tm *tblock
timer=time(NULL)
tblock=localtime(&timer)
printf("Local time is: %s",asctime(tblock))
return 0
}
@函数名称: asctime
函数原型: char* asctime(struct tm * ptr)
函数功能: 得到机器时间(日期时间转换为ASCII码)
函数返回: 返回的时间字符串格式为:星期,月,日,小时:分:秒,年
参数说明: 结构指针ptr应通过函数localtime()和gmtime()得到
所属文件: <time.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
int main()
{
struct tm t
char str[80]
t.tm_sec=1
t.tm_min=3
t.tm_hour=7
t.tm_mday=22
t.tm_mon=11
t.tm_year=56
t.tm_wday=4
t.tm_yday=0
t.tm_isdst=0
strcpy(str,asctime(&t))
printf("%s",str)
return 0
}
@函数名称: ctime
函数原型: char *ctime(long time)
函数功能: 得到日历时间
函数返回: 返回字符串格式:星期,月,日,小时:分:秒,年
参数说明: time-该参数应由函数time获得
所属文件: <time.h>
#include <stdio.h>
#include <time.h>
int main()
{
time_t t
time(&t)
printf("Today's date and time: %s",ctime(&t))
return 0
}
@函数名称: difftime
函数原型: double difftime(time_t time2, time_t time1)
函数功能: 得到两次机器时间差,单位为秒
函数返回: 时间差,单位为秒
参数说明: time1-机器时间一,time2-机器时间二.该参数应使用time函数获得
所属文件: <time.h>
#include <time.h>
#include <stdio.h>
#include <dos.h>
#include <conio.h>
int main()
{
time_t first, second
clrscr()
first=time(NULL)
delay(2000)
second=time(NULL)
printf("The difference is: %f seconds",difftime(second,first))
getch()
return 0
}
@函数名称: gmtime
函数原型: struct tm *gmtime(time_t *time)
函数功能: 得到以结构tm表示的时间信息
函数返回: 以结构tm表示的时间信息指针
参数说明: time-用函数time()得到的时间信息
所属文件: <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <dos.h>
char *tzstr="TZ=PST8PDT"
int main()
{
time_t t
struct tm *gmt, *area
putenv(tzstr)
tzset()
t=time(NULL)
area=localtime(&t)
printf("Local time is:%s", asctime(area))
gmt=gmtime(&t)
printf("GMT is:%s", asctime(gmt))
return 0
}
@函数名称: time
函数原型: time_t time(time_t *timer)
函数功能: 得到机器的日历时间或者设置日历时间
函数返回: 机器日历时间
参数说明: timer=NULL时得到机器日历时间,timer=时间数值时,用于设置日历时间,time_t是一个long类型
所属文件: <time.h>
#include <time.h>
#include <stdio.h>
#include <dos.h>
int main()
{
time_t t
t=time()
printf("The number of seconds since January 1,1970 is %ld",t)
return 0
}
@函数名称: tzset
函数原型: void tzset(void)
函数功能: UNIX兼容函数,用于得到时区,在DOS环境下无用途
函数返回:
参数说明:
所属文件: <time.h>
#include <time.h>
#include <stdlib.h>
#include <stdio.h>
int main()
{
time_t td
putenv("TZ=PST8PDT")
tzset()
time(&td)
printf("Current time=%s",asctime(localtime(&td)))
return 0
}
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)