您的位置:首页 > 编程语言

《编程珠玑》读书笔记

2008-03-24 09:08 239 查看
---------------------------基本原则------------------------
1、仔细分析小问题有时可带来巨大的实际好处
2、要打破概念上的障碍,转而解决一个更简单的问题,才能有效地解决问题
3、不要勿勿忙忙将第一灵感编写为程序,应该在编码之前进行充分的思考、权衡和抉择,以找出最有效的算法和设计
4、能用小的程序的话就不要编写大程序
5、数据结构对软件的贡献极大:
a.可将大程序缩减为小程序,以及时间和空间的缩减,增加可移值性和可维护性
b.凝神考虑数据,通常会打到更为有效的方法
c.表示法是编程的精华
6、编程中需要考虑的几个原则:
a.将重复性代码改写到数组中
b.封装复杂的结构
c.尽可能使用高级工具
d.让数据去构造程序
7、编码技能只能构成编写正确程序的一小部分,大部分任务是要:问题定义、算法设计以及数据结构选择
8、即使有了最优秀的设计,也必须编写精细的代码
9、平均值始终在两个值之间
10、契约式编程:假定如果调用该函数时满足前置条件的话,那么函数的执行将确立其后置条件。一旦证明了函数体具有此属性,我们就可使用前置条件和后置条件之间的这种陈述关系,而不需要再次考虑实现问题
11、保持代码的简单性通常是正确性的关键
12、使用断言来发现程序中潜在的错误
13、编写脚手架测试程序来对代码进行自动化测试
14、对于高难度的函数,最简单的方法就是先使用便利的高级伪码为其描绘框架,然后将其转换为实现语言
15、如果对运行时间要求不高,采用线性查找要比二分查找简单得多

---------------------------性能问题------------------------
1、程序中要实现可观的运行加速,需要在不同层次对程序进行优化
a.采用高效的算法和有效的数据结构
b.算法优化
c.对数据结构进行重组
d.代码优化,由于程序中往往80%的运行时间被某个低效的函数或一小段程序所占用,使用高效的语言(如汇编语言)或高效的算法重写该函数或那段代码
e.硬件
2、将大系统分解为模块可能是确定性能时最重要的单个因素。因为在新系统中获得效率要比在现有系统中进行效率改进容易得多,所以性能分析在系统设计期间是很关键的
3、更改系统所依赖的软件要比更改系统本身还简单,比如使用更块的数据库系统、操作系统,启用所有的编译器优化选项
4、如果需要少许加速,则研究最好的层次。即选择能够得到最大加速而所需的精力又最少的那个层次
5、如果需要更大的加速,则深入研究多重层次。
6、多进行封底计算来估计运行时间
以下是一些提示:
a.两个答案要比一个答案好
b.快速检测
c.经验法则:如“72法则”(如果投入了一笔钱,时间是y年,利率为每年r%,如果r*y=72,那么大致说来投入的钱就会翻倍)
7、性能估计(时间和空间)
8、安全系数
要承认在对我们的实时软件系统进行性能计算时,我们必须按照2、4或6的系统降低性能,以补偿我们的无知;在进行可靠性/可用性承诺时,我们应该对我们认为能够满足的目标保留一个10的系数,以补偿我们的无知;在估计规模、成本以及进度时,应该保留2或4的系数,以补偿我们在某个方面的缺漏。
9、利特尔法则
“系统中物体的平均数量就是系统中物体离开系统的平均比率和每个物体在系统中所花费的平均时间的乘积”,用在计算机系统中,就是:“队列中的平均物体数量是离队率和平均滞留时间的乘积”
10、设计原则:任何事都应该做到尽可能的简单,除非没有更简单的了
11、复杂算法有时可以极大地提高性能
12、几个重要的算法设计技术:
a.保存状态。避免重新计算。通过使用一些空间来保存各个结果,我们就可以避免因重新计算而浪费时间
b.将信息预处理到数据结构中。可以有效地缩短运行时间
c.分治算法。
d.扫描算法。有关数组的问题经常可以通过询问“我如何可以将x[0..i-1]的解决方案扩展为x[0..i]的解决方案?”的方式得到解决。
e.累积。如使用累积表,第i个元素包含x中前i个值的总和;在处理范围时,这一类表很常见。
f.下限。只有了解到算法已经是解决某类问题的可能算法中最佳时,才表明该算法已是最棒的。
13、提高效率的高层方法:问题定义、系统结构、算法设计以及数据结构选择。
14、代码优化是提高效率中一个较底层方法,用以确定现在程序中的开销昂贵的部分,然后作一些小小更改,提高其速度。该方法并不总是适当的方法,并且很少能吸引人,但是它有时确定可以使程序的性能大不一样。

15、常见的优化问题:
a.问题1--整数求余,如将 k = (j + rotdist) % n 改为:
k = j + rotdist;
if (k >= n) k -= n;
上述代码使用比较及(很少使用的)减法运算符替换了昂贵的%运算符
b.如果某个程序将时间主要花费在输入输出上,企图加速该程序中的计算将毫无价值。在现代的体系结构中,如果过多的周期花在访问内存上时,企图减少计算时间同样是毫无价值。
c.问题2--函数,宏以及内联代码。尽量不要使用宏(虽然在C中比函数调用性能高,但容易导致错误),而应该使用函数(C)或内联函数(C++),其中内联兼有了函数干净利落的语义和宏的低开销。
d.问题3--顺序查找:使用哨兵可以有效地减少代码中的测试次数,从而提高代码的运行速度。在现代的机器中将循环展开有助于避免流水线阻塞,减少分支,增加指令级的并行,从而显著地提高代码的运行速度。

16、代码优化的原则:尽量少用代码优化
a.效率的角色。软件中的许多其他属性和效率一样重要,甚至更重要。不成熟的优化是大量编程灾难的根源;它会危及程序的正确性、功能性以及可维护性。当这一点很重要时,请考虑适当将效率放一放。
b.度量工具。当效率变得重要时,第一步就是对系统进行配置,找出花费时间的位置。对程序进行profile描述时一般都会显示大多数的时间都花在少量的热点位置上了,而余下的代码则很少执行。对程序进行剖析将指出关键的区域;对于其他区域,就“没有坏的话就不要修改它”
c.设计层次。在优化代码前,应确保其他方法不会提供更加有效的解决方案
d.当加速的同时会减慢时。如,使用if语句替换%求余运算或以得到两倍的加速;而其他时候,对运行时间的影响则没有什么差别。将函数转换为宏可以两倍加速某一函数,但对于另一函数又可能减慢10000倍。
e.利用代数恒等式、使用宏(有保留地使用)来替换函数或使用内联函数、标记值(哨兵)测试、循环展开、扩展数据结构、使用合并测试将循环内部的比较次数尽可能减少、利用代数恒等式将上下限的表示方法更改为下限和增量表示法、循环展开将程序展开以消除所有的循环开销

17、减少空间通常带来运行时间上合理的副作用:程序越小,加载的时候也就越快,也越容易填充到高速缓存中;需要操作的数据越少,操作时所花的时间通常也就越少。

18、关键在于简单性:简单性可以产生功能性、健壮性以及速度和空间;简单性也可以减少代码的空间。以下是几种数据空间技术:
a.不要保存,重新计算。无论什么时候,在我们需要某一对象时,我们都不保存它,而是对它进行重新
计算,那么保存该对象所需的空间可以急剧地减少。如,一个素数表将被一个检索素数函数所取代。此方法牺牲更多的运行时间来获得更少的空间。这种方法只适用于待存储的对象可以从其描述中重新计算时的情形
,因为这样可以通过已经保存的较少的可描述某对象的信息中重建或重新生成该对象,而无需保存整个(较大)对象。
b.稀疏数据结构。
c.数据压缩。信息理论告诉我们,通过压缩的方式编码对象可以减少空间。如,通过整数 c=10 * a + b,将两个十进制数字a和b编码在一个字节中。该信息可以通过以下两个语句进行解码:
a = c / 10
b = c % 10
d.分配策略。通过在需要时才分配记录的方式动态分配记录可以避免预先分配而未完全使用的浪费现象。动态分配显示,在需要什么东西之前,我们不必请求那些东西;可变长度记录的策略告诉我们当我们确定需要请求某样东西时,我们应该根据需要量的多少来申请。
e.垃圾回收。回收废弃的内存之后,那些旧的位就又像新的一样了。如堆排序算法重叠了两个逻辑数据结构,它们在不同的时间应用于相同的物理存储位置。虽然现代计算机系统都有很在的内存,但为了提高性能,需要使用系统高速缓存,这样,又需要减少代码和数据所占的空间了。

18、编码空间技术。有时空间的瓶颈不在于数据,而在于程序本身的大小。下面是几乎用于减少代码空间的几种通用技术。
a.函数定义。通过用函数替换代码中的公共模式简化了程序,因而也就减少了它的空间需求,并增加了其清晰性。使系统维护起来更加简单,同时也减少了空间。如微软将整个Windows系统向下压缩为更加紧凑的window CE所使用的技术。
b.解释器。如用较少字节的解释器命令去替换硬编码到程序中长的文本数据,可以有效地减少程序所占用的空间。
c.手工将代码转换成机器语言或汇编语言,但这种方式很少有人使用,只在内存非常宝贵的系统中才使用。

19、空间压缩的原则
a.空间成本是否很高
b.空间中的“热点”。正如程序的运行时间通常聚集在一些热点上:即代码中的少量部分经常要占用大部分的运行时间,数据也同样具有热点:少数常见类型的记录经常要占用大部分的内存。
c.度量空间。使用性能监视器对程序运行时的内存使用情况进行观察,以了解程序是否存在对内存的不合理使用或过度使用以及内存泄漏的情况。
d.权衡。有时必须权衡放弃性能、功能性或可维护性以获得内存,这一类工程决策只适用于在所有可选办法都研究过之后才能作出。无论何时,在我们权衡放弃任意希望得到的特性之前,我们都应该寻找各种技术,努力改善我们解决方案中的方方面面。
e.和环境协作。编程环境对于程序的空间效率具有重要的影响。重要部分包括编译器和运行时系统所使用的表示方式、内存分配策略以及分页策略。
f.使用合适的作业工具。

20、编程原则:
a.理解观察到的问题。和用户讨论问题出现的环境。通常问题描述中就包含了解决方法的基本思想;just as usual, 必须考虑这些方法,但是不能排除其他的解决方法。
b.指定一个抽象问题。一个简洁、明确的问题描述能够帮助我们在解决这个问题的基础上,进一步考虑如何将这个解决方法应用到其他问题上。
c.利用设计空间。好的做法是宁愿思考一小时,编码一小时,而不是思考一分钟,编码一天。可以使用非正式的高级语言来描述设计:伪代码代表控制流,抽象数据类型代表关键的数据结构。这在设计过程阶段非常重要。
d.实现解决方法。通过研究空间有时可以发现某个程序比其他的要好;而有时则只好从较好的几个解决方法中选择最好的。尽量使用简单直白的代码实现选中的设计,使用可用的最强大的操作
e.回顾。回顾编程对于深入理解问题并寻到更有效的解决办法非常有用。
f.多花几分钟时间来寻找一个简单的程序往往能节省几个小时编写复杂程序的时间。

21、有关存储分配和递归:
a.在具有更高效率的分配器的不同系统中,消除递归能够将加速系统变为5。类似于很多代码优化技巧,缓存和递归消除有时会带来很多好处,但是有时却没什么用处。

22、实现查找算法的原则
a.库的作用。C++标准模板库提供了一个很容易实现、维护及扩展的通用解决方案。当面临的问题涉及到数据结构时,第一个反应应该是去查找解决问题的通用工具。
b.空间重要性。顺序访问内存可以极大地提高效率,因为这样可以充分利用CPU缓冲
c.代码优化技巧。最大的改进就是通过单独分配一个大块来替换通用内存分配。这消除了很多昂贵的调用,并能高效地利用空间。通过重写递归函数,将它变成迭代函数,可以有效地提高运行速度和减少空间。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: