程序性能分析
2017-01-07 17:55
183 查看
对一个程序来说,正确性是最重要的。若程序不能完成指定的任务,它就没有什么用处。然而,程序即使能完成任务,但资源消耗过大,那它也没有什么意义。
本文旨在概述程序性能分析的一些概念、两个简单的分析方法和渐进记法
1. 程序性能分析的一些概念
程序性能:指运行一个程序所需要的内存和时间的多少。用两种方法来确定程序的性能,分析方法和试验方法。在性能分析的时候,采用分析方法;在性能测量的时候采用试验方法。
空间复杂度:程序运行是所需要的内存的大小。由指令空间(代码段)、数据空间(初始化及未初始化的全局变量和静态变量)和环境栈空间(局部变量和自动变量)构成。影响空间复杂度的因素有很多,如目标计算机、编译器、程序的时间算法等。
时间复杂度:程序运行所需要的时间,包括编译时间和运行时间。
2. 分析方法
影响程序性能的因素很多,在性能分析时并不能给出精确的结论。不过,程序要处理的问题都有一些特征,这些特征包含着可以决定程序性能的因素,如输入和输出的规模、相关数的大小等。一般来说,我们的选择仅限于输入输出规模,记实力特征为n。
空间复杂度分析
空间复杂度 = C + Sp(n)
其中,C为固定部分,它与实力特征没有关系,包括代码和全局变量和静态变量;Sp(n)为可变部分,依赖于实力特征n,我们主要分析这一部分。
以n的阶乘函数来举例说明一下,假设int类型占用4个字节:
迭代法:Sp(n) = 4 + 4 + 4+ 4 = 16 (字节)
递归法:Sp(n) = (4 + 4) * max{n, 1} = 8max{n, 1} (字节)
所以说,迭代法阶乘空间复杂度为常量,递归法阶乘的空间复杂度随n线性增长。
时间复杂度分析
编译时间与实力特征无关,所以我们只关心程序运行时间,Tp(n)。
有两个较容易的方法: 1) 计算关键操作的执行次数; 2) 确定程序总的步数。这里不详述如何确定关键操作和程序的一步,提示一点:关键操作一般是比较耗时的操作,程序的一步必须独立于实力特征。
还是以阶乘函数为例,这里假设n > 0:
迭代法 :若按照方法1,将result *= i; 视为关键操作,那么Tp(n) = n - 1 ;
若按照方法2,如下:
可见方法1忽略掉了部分步骤,如result定义、for循环条件判断。
递归法:按照方法2:
所以,两种阶乘算法的函数的时间复杂度都随实力特征n线性增长。
3. 渐进记法
定义:令p(n)和q(n)是两个非负函数。称p(n)渐进地大于q(n),当且仅当n趋于无穷大时,q(n)/p(n) = 0;称q(n)渐进地小于p(n);称p(n)渐进地等于q(n),当且仅当任何一个都不渐进地大于另一个。
记法:
f(n) = O(g(n)):代表f(n)渐进小于或等于g(n);
f(n) =
Ω(g(n)):代表f(n)渐进大于或等于g(n);
f(n) =
Θ(g(n)):代表f(n)渐进等于g(n);
f(n) = o(g(n)):代表f(n)渐进小于g(n);
在步数分析中经常出现的项有:1 < logn < n < nlogn < n^2 < n^3 < 2^n < n!
上述阶乘函数的时间复杂度Tp(n) =
Θ(n)。
在程序性能分析中,通常会涉及到最好、最坏和平均操作计数。前两者比较简单,平均操作计数要用到概率的知识,比较复杂。
本文旨在概述程序性能分析的一些概念、两个简单的分析方法和渐进记法
1. 程序性能分析的一些概念
程序性能:指运行一个程序所需要的内存和时间的多少。用两种方法来确定程序的性能,分析方法和试验方法。在性能分析的时候,采用分析方法;在性能测量的时候采用试验方法。
空间复杂度:程序运行是所需要的内存的大小。由指令空间(代码段)、数据空间(初始化及未初始化的全局变量和静态变量)和环境栈空间(局部变量和自动变量)构成。影响空间复杂度的因素有很多,如目标计算机、编译器、程序的时间算法等。
时间复杂度:程序运行所需要的时间,包括编译时间和运行时间。
2. 分析方法
影响程序性能的因素很多,在性能分析时并不能给出精确的结论。不过,程序要处理的问题都有一些特征,这些特征包含着可以决定程序性能的因素,如输入和输出的规模、相关数的大小等。一般来说,我们的选择仅限于输入输出规模,记实力特征为n。
空间复杂度分析
空间复杂度 = C + Sp(n)
其中,C为固定部分,它与实力特征没有关系,包括代码和全局变量和静态变量;Sp(n)为可变部分,依赖于实力特征n,我们主要分析这一部分。
以n的阶乘函数来举例说明一下,假设int类型占用4个字节:
//迭代法 int factorial_iteration(int n) //参数n,4个字节 { int result = 1; //result,4个字节 for(int i = n; i > 1; i--) //i,4个字节 result *= i; return result; //返回地址,指针类型4个字节 } //递归法 int factorial_recursion(int n) //参数n,4个字节 { if(n > 1) return n * factorial_recursion(n - 1); else return 1; //返回地址,指针类型4个字节 }
迭代法:Sp(n) = 4 + 4 + 4+ 4 = 16 (字节)
递归法:Sp(n) = (4 + 4) * max{n, 1} = 8max{n, 1} (字节)
所以说,迭代法阶乘空间复杂度为常量,递归法阶乘的空间复杂度随n线性增长。
时间复杂度分析
编译时间与实力特征无关,所以我们只关心程序运行时间,Tp(n)。
有两个较容易的方法: 1) 计算关键操作的执行次数; 2) 确定程序总的步数。这里不详述如何确定关键操作和程序的一步,提示一点:关键操作一般是比较耗时的操作,程序的一步必须独立于实力特征。
还是以阶乘函数为例,这里假设n > 0:
迭代法 :若按照方法1,将result *= i; 视为关键操作,那么Tp(n) = n - 1 ;
若按照方法2,如下:
程序 | 操作包含步数s/e | 频率f | 总的步数 |
int result = 1; | 1 | 1 | 1 |
for(int i = n; i > 1; i--) | 1 | n | n |
result *= i; | 1 | n - 1 | n - 1 |
return result; | 1 | 1 | 1 |
Tp(n) = | 2n + 1 |
递归法:按照方法2:
程序 | 操作包含步数s/e | 频率f | 总的步数 |
if(n > 1) | 1 | n | n |
return *; | 1 | n | n |
Tp(n) = | 2n |
3. 渐进记法
定义:令p(n)和q(n)是两个非负函数。称p(n)渐进地大于q(n),当且仅当n趋于无穷大时,q(n)/p(n) = 0;称q(n)渐进地小于p(n);称p(n)渐进地等于q(n),当且仅当任何一个都不渐进地大于另一个。
记法:
f(n) = O(g(n)):代表f(n)渐进小于或等于g(n);
f(n) =
Ω(g(n)):代表f(n)渐进大于或等于g(n);
f(n) =
Θ(g(n)):代表f(n)渐进等于g(n);
f(n) = o(g(n)):代表f(n)渐进小于g(n);
在步数分析中经常出现的项有:1 < logn < n < nlogn < n^2 < n^3 < 2^n < n!
上述阶乘函数的时间复杂度Tp(n) =
Θ(n)。
在程序性能分析中,通常会涉及到最好、最坏和平均操作计数。前两者比较简单,平均操作计数要用到概率的知识,比较复杂。
相关文章推荐
- 选定虚拟主机 性能凸显优势
- 修改一行代码提升 Postgres 性能 100 倍
- redis的hGetAll函数的性能问题(记Redis那坑人的HGETALL)
- 推荐Sql server一些常见性能问题的解决方法
- 通过使用正确的search arguments来提高SQL Server数据库的性能
- SQL Server误区30日谈 第9天 数据库文件收缩不会影响性能
- 和表值函数连接引发的性能问题分析
- SQLServer 2000 升级到 SQLServer 2008 性能之需要注意的地方之一
- 数据库性能优化三:程序操作优化提升性能
- C#中Dynamic和Dictionary性能比较
- VBS中的字符串连接的性能问题
- mysql 性能的检查和调优方法
- 数据库性能优化二:数据库表优化提升性能
- SQL语句性能优化(续)
- SQL语句优化提高数据库性能
- 如何用分表存储来提高性能 推荐
- ASP中使用FileSystemObject时提高性能的方法
- 如何改进javascript代码的性能
- JavaScript脚本性能优化注意事项
- 使用Function.apply()的参数数组化来提高 JavaScript程序性能的技巧