系统级程序设计笔记(unit5——程序性能)

本文介绍了衡量和分析程序性能的方法,包括使用不同度量方法及其优缺点,解释了CPU时间、墙上时间的概念,并讨论了进程调度、定时器中断的作用。还介绍了如何利用专属时间和包含时间来识别程序中的热点,以及应用阿姆达尔定律来评估性能优化的效果。

这个专题的所有学习笔记来自于对武汉大学计算机学院软件工程专业大三上学期的专业必修课《系统级程序设计》的学习(教材为深入理解计算机系统CSAPP),涉及的编程语言全部为C语言和C++语言。

该博客为第5单元的学习笔记,这一单元的主要内容是衡量分析程序性能、热点、阿姆达尔定律等。对应ssd6课程的lecture6。


对程序性能的衡量和分析

(1)①理解程序慢的原因:有个别地方占去了很多时间。
②设计并实现解决方案:用最小的代价实现最大的加速。
迭代步骤1和步骤2,直到表现令人满意或者直到剩余的优化不值得为优化进行努力为止。
在程序消耗了大部分的时间的地方进行性能的衡量。

(2)CPU时间(CPU Time):该进程占用CPU的总时间,包括了用户时间(User time)系统时间(System time),用于指令的执行
用户时间:用户进程获得CPU资源后,在用户态执行的时间
系统时间:用户进程获得CPU资源后,在内核态执行的时间
墙上时间(Wall Time):计算机执行某个任务的实际时间,即任务从提交到完成所用的时间 (ps:和CPU time的区别在于Wall time包含了程序中的延迟(如sleep函数调用)和等待资源和阻塞状态的时间)
墙上时间 = 阻塞时间 + 就绪时间 +运行时间

(3)时间规模:计算机在两个根本不同的时间规模上运行
微观上:以一个或多个时钟周期的等级规模来执行指令,其中每个时钟周期只需要大约一纳秒(缩写为“ns”)
宏观上:处理器必须响应以毫秒为单位的时间规模上发生的外部事件(缩写为“ms”)。

举例:在视频播放过程中,大多数计算机的图形显示必须每33毫秒刷新一次。
世界纪录打字员只能以每50毫秒一次的速度敲击键盘。
磁盘通常需要大约10毫秒才能启动磁盘传输。
处理器在一个宏观的时间尺度上不断地在这些任务之间切换,每次都要花费大约5到20毫秒的时间。
人们无法辨别短于100毫秒左右的时间。在这段时间内,处理器可以执行数以百万计的指令。

(4)进程调度和定时器中断
计算机有一个外部定时器,周期性地产生一个中断信号给处理器。
这些中断信号之间的间隔称为间隔时间。(interval time)
当发生计时器中断时,OS调度器可以选择恢复当前正在执行的进程或切换到不同的进程。
必须将此间隔设置得足够短,以确保处理器将在任务之间切换。
典型的计时器间隔在1到10毫秒之间。

定时机制
①直接使用定时器
precise.zip中的percise.cpp使用精密定时器测量时间
②使用统计抽样
Timer periodically interrupts the program and records the program counter or increments a counter representing a range of program counters
定时器周期性地中断程序并记录程序计数器或增加表示一个程序计数器范围的计数器。

(5)在测量应用程序性能时,通常采用的度量方法有几种?分别阐述它们的优缺点
①工具度量法。该方法采用系统工具,度量的是应用程序总体运行时间,实际占用CPU时间,以及其它应用程序占据CPU的时间等。
②代码方法。该方法通过自定义的代码函数,测量应用程序实际占用CPU的时间。
③Profile方法。通过对应用程序运行时采样,度量应用程序占用CPU的时间。
④以上3种方法均可以度量应用程序占用CPU的时间,这在多任务系统中非常有效,可以排除其他应用程序占用CPU的时间。工具度量法与代码方法的优点是简单;但是不能细化度量应用程序中函数对CPU占用的时间分布;对于应用程序优化帮助不大。Profiling方法的优点是可以度量应用程序中各个函数对于CPU占用的时间分布,可以帮助调试寻找应用程序的HOT SPOT,从而发现应用程序最值得优化的部分,缺点是该方法必须针对源代码进行调试。

(6)这里写图片描述
这一行显示的前三个数字是时间。
前两个显示的是用户时间(u)和系统时间(s)的秒数。
在一个间隔为10毫秒的时间间隔中,所有的时间都是1/100秒的倍数。第三个数字是所经过的总时间。
观察系统和用户时间总和为2.49秒,不到6.52秒的时间的一半。
百分比表示联合用户和系统时间所占时间的百分比,例如(2.23 + 0.26)/ 6.52 = 0.381。
其余的统计数据总结了分页和I/O行为。

程序性能可以通过以下方式被测量
★计算运行程序的运行时间、统计抽样(分析)
★计时器来测量运行时间
★分析器用来分析,以帮助确定需要优化什么
★系统资源监视器:CPU时间、内存使用、输入输出行为

(7)这里写图片描述
如果b调用了a,那么b是a的caller,a是b的callee

Exclusive time专属时间是该函数本身基本操作(不包括子函数调用)的时间。不包括花在其被调者的时间,暂停时间和程序分析器的时间
Inclusive time是该函数调用所用的时间(包括子函数调用)的时间。包括被调用时间,暂停时间和事件探查器的时间
Callee Exclusive Time被调用的专属时间:花在函数和它的子函数调用的总时间,不包括暂停时间和程序分析器的时间
Callee Time被调用的时间:花在子函数调用上的总时间(包括暂停时间和在子函数调用下的程序分析器的时间)
暂停时间:暂停时间
分析时间:程序分析器所花费的总时间

热点

(1)80/20法则:80%的CPU时间用于程序的20%。
这些计算机所花的大部分时间的地方,也被称为热点(hot spots)

(2)阿姆达尔定律(2017-2018学年期末考试考过)
PPT:所有的程序都有热点,一点小的努力和优化就可以获得比较大的回报。
如果程序只有一部分可以通过进行并行处理而加速,那么程序的连续部分将会确定和限制一个可能的速度。
懂得如何优化是一项重要的技能。知道何时停止优化也是很重要的。

课本:当我们对系统的某个部分加速时,其对系统整体性能的影响取决于该部分的重要性和加速程度。若系统执行某应用程序需要时间为ToldTold,假设该系统某部分所需执行时间与执行该应用程序总时间的比例为α,而该部分的性能提升比例为k,即该部分初始所需时间为αToldαTold,现在所需时间为αTold/kαTold/k,因此总的执行时间应为

Tnew=(1α)Told+(αTold)/kTnew=(1−α)Told+(αTold)/k

进一步计算出加速比如下:

S=ToldTnew=11α+α/kS=ToldTnew=11−α+α/k

举个例子,系统的某个部分初始的耗时比例为60%(α=60%),其加速比例因子为3(k=3)。则我们可以获得的加速比为1/(0.4+0.6/3)=1.67倍。
虽然我们对系统的一个主要部分做出了重大改进,但是获得的系统加速比却明显小于这部分的加速比,这就是阿姆达尔定律的主要观点——想要显著加速整个系统必须提升全系统中相当大的部分的速度。
阿姆达尔定律一个有趣的特殊情况是考虑k趋向于无穷大时的效果,也就是说把某一部分加速到不费时间,我们得到

S=11αS∞=11−α ;k->∞

举个例子,如果60%的系统可以加速到不花时间的程度,我们获得的净加速比也只有2.5倍而已。

(3)printf()中的malloc()
printf()函数使得malloc在正常的实现中被调用,从而增加了不希望的开销。
无论是作为在printf中对文本进行格式化,阅读ASCII文本并转化成为数字,还是执行字符串的比较,字符串的操作都是昂贵的
现在计算机的设计是一次访问内存存取一个单词,访问单个字符并不比访问一个单词更快,而且可能还会更慢一点。
通常情况下,字符串操作一次操作一个字符,比如setlen(),必须执行每一个字符,每一次一个。

在malloc()中
使用静态变量或局部变量,从而避免在堆上分配内存;
维护一个存储经常需要被分配空间的对象的列表->显式空闲链表,从而实现:分配仅仅是从列表中移除一个对象,而释放只是在列表中插入对象。

快速分配和释放:使用一大块内存,从中分配较小的块来计算一些结果。在得到结果之后,整个块被释放,这是非常快的,因为:
通过你需要分配的字节的数目来移动空闲指针,内存通过这种方式简单地实现被分配。
没有必要释放每一个分配的对象,你可以通过立刻释放整个池的方法来释放所有的对象。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值