内容提要 测试、性能和可扩展性 ■测试 ■性能 邢国峰 可扩展性 2007-11-28 20u7-1 测试,性能和可扩展性 试.性能和可护展性 测试 测试vs.调试 测试vs.调试 调试( Debug):在程序无法运行或输出结果错 测试的目的与原则 误时,通过设置断点、打印变量值和跟踪等 测试策略 方法定位并排除bug 测试方法 测试( Testing):调试通过后,用系统的方法 来试图发现程序中可能存在的隐藏的bug,避 免这些bug出现在发行版本中 调试——已知bug,用于定位并排除bug。 测试——未知bug,用于发现bug 2007-1128 试、性能和可扩展性 2007-11-28 测试,性能和可扩展性 测试的目的 测试的原则 1测试是程序的执行过程,目的在于发现错误 1.应当把“尽早地和不断地进行软件测试”作 为软件开发者的座右铭 2.一个好的测试用例在于能发现至今未发现的 2.测试用例应由测试输入数据和对应的预期输 错误 出结果这两部分组成 3.一个成功的测试是发现了至今未发现的错误 3.程序员应避免检查自己的程序。 的测试 4.在设计测试用例时,应包括合理的输入条件 和不合理的输入条件 207-1128 拥试,性能和可扩展性 20u711-28 性能和可扩展性
测试、性能和可扩展性 邢国峰 2007-11-28 2007-11-28 测试、性能和可扩展性 1 2007-11-28 测试、性能和可扩展性 2 内容提要 测试 性能 可扩展性 2007-11-28 测试、性能和可扩展性 3 测试 (测试 vs. 调试 (测试的目的与原则 (测试策略 (测试方法 2007-11-28 测试、性能和可扩展性 4 测试 vs. 调试 调试(Debug):在程序无法运行或输出结果错 误时,通过设置断点、打印变量值和跟踪等 方法定位并排除bug。 测试(Testing):调试通过后,用系统的方法 来试图发现程序中可能存在的隐藏的bug,避 免这些bug出现在发行版本中。 调试——已知bug,用于定位并排除bug 。 测试——未知bug,用于发现bug。 测试的目的 1.测试是程序的执行过程, 目的在于发现错误 ; 2.一个好的测试用例在于能发现至今未发现的 错误; 3.一个成功的测试是发现了至今未发现的错误 的测试。 2007-11-28 测试、性能和可扩展性 5 测试的原则 1.应当把“尽早地和不断地进行软件测试”作 为软件开发者的座右铭。 2. 测试用例应由测试输入数据和对应的预期输 出结果这两部分组成。 3. 程序员应避免检查自己的程序。 4. 在设计测试用例时,应包括合理的输入条件 和不合理的输入条件。 2007-11-28 测试、性能和可扩展性 6
测试的原则 Bug报告 5.严格执行测试计划,排除测试的随意性 6.应当对每一个测试结果做全面检查 严程度 7.妥善保存测试计划,测试用例,出错统计和 最终分析报告,为维护提供方便 版本转换比想片,提解析M,种后口上时可正富使用, 20u7-1 拥试、性能和可扩展性 试.性能和可护展性 测试策略 单元测试,一一程序员负责 测试过程按4个步骤进行: 集中对用源代码实现的每一个程序单元 进行测试,检查各个程序模块是否正确地实 单元测试 现了规定的功能 集成测试 确认测试 集成测试把已测试过的模块组装起来,主要 系统测试 对与设计相关的软件体系结构的构造进行测 2007-1128 试、性能和可扩展性 2007-11-28 测试,性能和可扩展性 确认测试则是要检查已实现的软件是否满足 举例:单元测试方案 单元微试方案 需求规格说明中确定了的各种需求,以及 软件配置是否完全、正确 单元功 读取R|P后的图像的RGB数据,利用M44算法进行压缩 利试要点 须测试压缩后的图象数据是否正确 系统测试—专门的测试部门负责 测试方法 编写测试代码,将压缩后的数据直接写到临时文件中,用Du 把已经经过确认的轼件纳入实际运行环 境中,与其他系统成份组合在一起进行测试 1 Imagel4Fero中加入测试代码 3察看测试代码生成的结构文件 测试样例 任何彩色和灰度图像 0r11-28 拥试,性能和可扩展性 20u711-28 性能和可扩展性
测试的原则 5. 严格执行测试计划,排除测试的随意性。 6. 应当对每一个测试结果做全面检查。 7. 妥善保存测试计划,测试用例,出错统计和 最终分析报告,为维护提供方便。 2007-11-28 测试、性能和可扩展性 7 Bug报告 2007-11-28 测试、性能和可扩展性 8 2007-11-28 测试、性能和可扩展性 9 测试策略 (测试过程按4个步骤进行: (单元测试 (集成测试 (确认测试 (系统测试 单元测试,——程序员负责 集中对用源代码实现的每一个程序单元 进行测试,检查各个程序模块是否正确地实 现了规定的功能。 集成测试把已测试过的模块组装起来,主要 对与设计相关的软件体系结构的构造进行测 试。 2007-11-28 测试、性能和可扩展性 10 确认测试则是要检查已实现的软件是否满足 了需求规格说明中确定了的各种需求,以及 软件配置是否完全、正确。 系统测试——专门的测试部门负责 把已经经过确认的软件纳入实际运行环 境中,与其他系统成份组合在一起进行测试 。 2007-11-28 测试、性能和可扩展性 11 举例:单元测试方案 单元测试方案表 单元功能 读取RIP后的图像的RGB数据,利用IW44算法进行压缩 测试要点 须测试压缩后的图象数据是否正确 测试方法 编写测试代码,将压缩后的数据直接写到临时文件中,用DjVu 阅读器打开验证 测试过程 1.ImageIW44Filter()中加入测试代码; 2.正常运行程序; 3.察看测试代码生成的结构文件 测试样例 任何彩色和灰度图像 2007-11-28 测试、性能和可扩展性 12
测试方法 黑盒测试 ■两种常用的测试方法 ■这种方法是把测试对象看做一个黑盒子,测 黑盒测试 试人员完全不考虑程序内部的逻辑结构和内 白盒测试 部特性,只依据程序的需求规格说明书,检 查程序的功能是否符合它的功能说明。 ■黑盒测试又叫做功能测试或数据驱动测试。 20u7-1 拥试、性能和可扩展性 试.性能和可护展性 黑盒测试 白盒测试 ■黑盒测试方法是在程序接口上进行测试,主要是 ■此方法把测试对象看做一个透明的盒子,它 为了发现以下错误 允许测试人员利用程序内部的逻辑结构及有 ◆是否有不正确或遗漏了的功能? 关信息,设计或选择测试用例,对程序所有 ◆在接口上,输入能否正确地接受?能否输出正确的结 逻辑路径进行测试 ◆是否有数据结构错误或外部信息访问错误? ■通过在不同点检查程序的状态,确定实际的 令性能上是否能够满足要求? 状态是否与预期的状态一致。因此白盒测试 是否有初始化或终止性错误? 又称为结构测试或逻辑驱动测试 试、性能和可扩展性 2007-11-28 测试、性能和可扩展性 白盒测试 测试用例设计原则 主要对程序模块进行如下的检査: 1.对程序模块的所有独立的执行路径至少测 测试用例的代表性:能够代表并覆盖各种合 式一次一路径覆盖测试 2.对所有的逻辑判定,取“真”与取“假” 理的和不合理、合法的和非法的、边界的和 都至少测试一次一逻辑覆盖测试: 越界的、以及极限的输入数据、操作和环境 3.在循环的边界和运行界限内执行循环体 控制流测试 设置等。 4.测试内部数据结构的有效性一数据流 测试、领域测试等 0r11-28 拥试,性能和可扩展性 20u711-28 性能和可扩展性
2007-11-28 测试、性能和可扩展性 13 测试方法 两种常用的测试方法 Z黑盒测试 Z白盒测试 黑盒测试 这种方法是把测试对象看做一个黑盒子,测 试人员完全不考虑程序内部的逻辑结构和内 部特性,只依据程序的需求规格说明书,检 查程序的功能是否符合它的功能说明。 黑盒测试又叫做功能测试或数据驱动测试。 2007-11-28 测试、性能和可扩展性 14 黑盒测试 黑盒测试方法是在程序接口上进行测试,主要是 为了发现以下错误: 是否有不正确或遗漏了的功能? 在接口上,输入能否正确地接受? 能否输出正确的结 果? 是否有数据结构错误或外部信息访问错误? 性能上是否能够满足要求? 是否有初始化或终止性错误? 2007-11-28 测试、性能和可扩展性 15 白盒测试 此方法把测试对象看做一个透明的盒子,它 允许测试人员利用程序内部的逻辑结构及有 关信息,设计或选择测试用例,对程序所有 逻辑路径进行测试。 通过在不同点检查程序的状态,确定实际的 状态是否与预期的状态一致。因此白盒测试 又称为结构测试或逻辑驱动测试。 2007-11-28 测试、性能和可扩展性 16 白盒测试 主要对程序模块进行如下的检查: 1.对程序模块的所有独立的执行路径至少测 试一次 — 路径覆盖测试; 2.对所有的逻辑判定,取“真”与取“假” 都至少测试一次 — 逻辑覆盖测试; 3.在循环的边界和运行界限内执行循环体 — 控制流测试; 4.测试内部数据结构的有效性 — 数据流 测试、领域测试等。 2007-11-28 测试、性能和可扩展性 17 测试用例设计原则 测试用例的代表性:能够代表并覆盖各种合 理的和不合理、合法的和非法的、边界的和 越界的、以及极限的输入数据、操作和环境 设置等。 2007-11-28 测试、性能和可扩展性 18
测试用例设计原则 黑盒测试用例设计 ■具体的黑盒测试用例设计方法包括等价类划 ■测试结果的可判定性:即测试执行结果的正 分法、边界值分析法、场景法、错误推测法 确性是可判定的,每一个测试用例都应有相 、因果图法、判定表驱动法、正交试验设计 应的期望结果 法、功能图法等。 测试结果的可再现性:即对同样的测试用例 ■在使用时,针对开发项目的特点对方法加以 ,系统的执行结果应当是相同的 适当的选择 20u7-1 拥试、性能和可扩展性 试.性能和可护展性 等价类划分法 划分等价类 等价类划分方法 等价类划分有两种不同的情况 把所有可能的输入数据,即程序的输入域划 冷有效等价类:是指对于程序的规格说明来说 分成若干部分(划分等价类); 是合理的、有意义的输入数据构成的集合, 然后从每一部分中选取少数有代表性的数据 做为测试用例(选取测试用例)。 利用有效等价类可检验程序是否实现了规格 说明中所规定的功能和性能。 ◆无效等价类:与有效等价类的定义恰巧相反 2007-1128 试、性能和可扩展性 2007-11-28 测试、性能和可扩展性 建立等价类表 确定测试用例 ■在确立了等价类之后,建立等价类表,列出 ■根据等价类表,按以下步骤确定测试用例: 所有划分出的等价类 1.为每个等价类规定一个唯一的编号 输入条件有效等价类无效等价类 2.设计一个新的测试用例,使其尽可能多地 覆盖尚未覆盖的有效等价类。重复这一步 最后使得所有有效等价类均被测试用例所覆 0r11-28 拥试,性能和可扩展性 20u711-28 性能和可扩展性
测试用例设计原则 测试结果的可判定性:即测试执行结果的正 确性是可判定的,每一个测试用例都应有相 应的期望结果; 测试结果的可再现性:即对同样的测试用例 ,系统的执行结果应当是相同的。 2007-11-28 测试、性能和可扩展性 19 黑盒测试用例设计 具体的黑盒测试用例设计方法包括等价类划 分法、边界值分析法、场景法、错误推测法 、因果图法、判定表驱动法、正交试验设计 法、功能图法等。 在使用时,针对开发项目的特点对方法加以 适当的选择。 2007-11-28 测试、性能和可扩展性 20 等价类划分法 等价类划分方法: 把所有可能的输入数据,即程序的输入域划 分成若干部分(划分等价类); 然后从每一部分中选取少数有代表性的数据 做为测试用例(选取测试用例)。 2007-11-28 测试、性能和可扩展性 21 划分等价类 等价类划分有两种不同的情况: 有效等价类:是指对于程序的规格说明来说 是合理的、有意义的输入数据构成的集合。 利用有效等价类可检验程序是否实现了规格 说明中所规定的功能和性能。 无效等价类:与有效等价类的定义恰巧相反 。 2007-11-28 测试、性能和可扩展性 22 建立等价类表 在确立了等价类之后,建立等价类表,列出 所有划分出的等价类: 2007-11-28 测试、性能和可扩展性 23 输入条件 有效等价类 无效等价类 ….. …… …….. 确定测试用例 根据等价类表,按以下步骤确定测试用例: 1.为每个等价类规定一个唯一的编号; 2.设计一个新的测试用例,使其尽可能多地 覆盖尚未覆盖的有效等价类。重复这一步, 最后使得所有有效等价类均被测试用例所覆 盖; 2007-11-28 测试、性能和可扩展性 24
确定测试用例 举例 ■根据下面给出的规格说明,利用等价类划分 的方法,给出足够的测试用例。 3.设计一个新的测试用例,使其只覆盖一个 “一个程序读入3个整数,把这三个数值看作 尚未被覆盖的无效等价类。重复这一步使所 一个三角形的3条边的长度值。这个程序要打 有无效等价类均被覆盖。 印出信息,说明这个三角形是不等边的、是 等腰的、还是等边的 20u7-1 拥试、性能和可扩展性 试.性能和可护展性 划分等价类 建立等价类表 ■我们可以设三角形的3条边分别为A,B,C。如果它 输入条件 有效等价类 无效等价类 们能够构成三角形的3条边,必须满足 A>0, B>0, C>0, EA+B>C, B+C>A, A+C>B 形的三 ■如果是等腰的,还要判断A=B,或B=C,或A=C ■如果是等边的,则需判断是否A=B,且B=C,且A=C 是否展dB6 ≠B)and(B≠c) (C=A) c≠A (16) 是否等边 A=B) and (B-c)and 三角形 c≠A) (20) 2007-1128 试、性能和可扩展性 确定测试用例 边界值分析法 A《1),(2),(3,(4),《5),《6 三角 边界值分析也是一种黑盒测试方法,是对等 【oba】c 价类划分方法的补充 不的三角添 人们从长期的测试工作经验得知,大量的错 B田 ,(,(),(4,(s,(B),《 误是发生在输入或输出范围的边界上,而不 【344】[tn,), 4,(,(b, 是在输入范围的内部。因此针对各种边界情 區蟲m,m:m皿 事三角 况设计测试用例,可以查出更多的错误 s33】(1, 是边三角 (),(I》,〔三角那 (,(3,(4,(,(B(),醉)」 20u711-28 性能和可扩展性
确定测试用例 3.设计一个新的测试用例,使其只覆盖一个 尚未被覆盖的无效等价类。重复这一步使所 有无效等价类均被覆盖。 2007-11-28 测试、性能和可扩展性 25 举例 根据下面给出的规格说明,利用等价类划分 的方法,给出足够的测试用例。 “一个程序读入3个整数,把这三个数值看作 一个三角形的3条边的长度值。这个程序要打 印出信息,说明这个三角形是不等边的、是 等腰的、还是等边的。” 2007-11-28 测试、性能和可扩展性 26 划分等价类 我们可以设三角形的3条边分别为A,B,C。如果它 们能够构成三角形的3条边,必须满足: A>0,B>0,C>0,且A+B>C,B+C>A,A+C>B。 如果是等腰的,还要判断A=B,或B=C,或A=C。 如果是等边的,则需判断是否A=B,且B=C,且A=C 。 2007-11-28 测试、性能和可扩展性 27 建立等价类表 输入条件 有效等价类 无效等价类 是否三角 形的三 条边 (A>0), (1) (B>0), (2) (C>0), (3) (A+B>C), (4) (B+C>A), (5) (A+C>B), (6) (A≤0), (7) (B≤0), (8) (C≤0), (9) (A+B≤C), (10) (B+C≤A), (11) (A+C≤B), (12) 是否等腰 三角形 (A=B), (13) (B=C), (14) (C=A), (15) (A≠B)and(B≠C)and (C≠A) (16) 是否等边 三角形 (A=B)and(B=C)and (C=A) (17) (A≠B), (18) (B≠C), (19) (C≠A), (20) 确定测试用例 序号 【A,B,C】 覆盖等价类 输出 1 【3,4, 5】 (1),(2),(3),(4),(5),(6) 一般三角形 2 【0,1,2】 (7) 不能构成三角形 3 【1,0,2】 (8) 4 【1,2,0】 (9) 5 【1,2,3】 (10) 6 【1,3,2】 (11) 7 【3,1,2】 (12) 8 【3,3,4】 (1),(2),(3),(4),(5),(6),(13) 9 【3,4,4】 (1),(2),(3),(4),(5),(6),(14) 等腰三角形 10 【3,4,3】 (1),(2),(3),(4),(5),(6),(15) 11 【3,4,5】 (1),(2),(3),(4),(5),(6),(16) 非等腰三角形 12 【3,3,3】 (1),(2),(3),(4),(5),(6),(17) 是等边三角形 13 【3,4,4】 (1),(2),(3),(4),(5),(6),(14),(18) 14 【3,4,3】 (1),(2),(3),(4),(5),(6),(15),(19) 非等边三角形 15 【3,3,4】 (1),(2),(3),(4),(5),(6),(13),(20) 边界值分析法 边界值分析也是一种黑盒测试方法,是对等 价类划分方法的补充。 人们从长期的测试工作经验得知,大量的错 误是发生在输入或输出范围的边界上,而不 是在输入范围的内部。因此针对各种边界情 况设计测试用例,可以查出更多的错误。 2007-11-28 测试、性能和可扩展性 30
边界值分析法 测试方法选择的综合策略 c首先进行等价类划分,包括输入条件和输出条件的等 bool TestBinPackO t 价划分,将无限测试变成有限测试 / This function test the boundary condition ca在任何情况下都必须使用边界值分析方法。经验表明 of the bin Pack Function * if BinPack (o)I=0)return false 用此方法设计出测试用例发现程序错误的能力最强 if BinPack (10)I= 26)return false; 对照程序逻辑,检查已设计出的测试用例的逻辑覆盖 return true. 程度。如果没有达到要求的覆盖标准,应当再补充足 20u7-1 拥试、性能和可扩展性 试.性能和可护展性 性能 CPU能做什么 编写高性能的代码是一门技术, 流水线—CPU指令可以重叠执行 ■也是一门艺术。 ■乱序执行——不相关指令可以乱序执 行 ■并行计算——多CPU共同完成一项计算 任务 ■超线程——用一块CP模拟对称多处理 的并行计算 2007-1128 试、性能和可扩展性 2007-11-28 测试、性能和可扩展性 编译器能作什么 编译器能作什么 GcC( GNU C Compiler)可以通过O选项来进 ■-O2第二级优化 行代码优化 包括O1的所有内容 ■-O1初级优化 ⌒a针对处理器指令调度的调整 线程直接跳转:避免复杂的进程切换 αa流水线处理:当处理器等待运算结果(比如除法) 延迟退栈 和二级缓存操作数时,可以执行其他指令 比如函数A调用函数B,B再调用函数C,当连续的函 数调用返回发生时,并不是每次返回都退栈,而是 B和C一起退栈 ■很多程序员热衷于-O2,它是时间效率和代码 大小的折中 0r11-28 拥试,性能和可扩展性 20u711-28 性能和可扩展性
边界值分析法 bool TestBinPack() { /* This function test the boundary condition * of the BinPack Function */ if ( BinPack(0) != 0 ) return false; if ( BinPack(10) != 26 ) return false; return true; } 2007-11-28 测试、性能和可扩展性 31 测试方法选择的综合策略 Z首先进行等价类划分,包括输入条件和输出条件的等 价划分,将无限测试变成有限测试。 Z在任何情况下都必须使用边界值分析方法。经验表明 用此方法设计出测试用例发现程序错误的能力最强。 Z对照程序逻辑,检查已设计出的测试用例的逻辑覆盖 程度。如果没有达到要求的覆盖标准,应当再补充足 够的测试用例。 2007-11-28 测试、性能和可扩展性 32 2007-11-28 测试、性能和可扩展性 33 性能 编写高性能的代码是一门技术, 也是一门艺术。 2007-11-28 测试、性能和可扩展性 34 CPU能做什么 流水线——CPU指令可以重叠执行 乱序执行——不相关指令可以乱序执 行 并行计算——多CPU共同完成一项计算 任务 超线程——用一块CPU模拟对称多处理 的并行计算 2007-11-28 测试、性能和可扩展性 35 编译器能作什么 GCC(GNU C Compiler)可以通过-O选项来进 行代码优化 -O1初级优化 Z线程直接跳转:避免复杂的进程切换 Z延迟退栈: 比如函数A调用函数B,B再调用函数C,当连续的函 数调用返回发生时,并不是每次返回都退栈,而是 B和C一起退栈 2007-11-28 测试、性能和可扩展性 36 编译器能作什么 -O2第二级优化 Z包括-O1的所有内容 Z针对处理器指令调度的调整 Z流水线处理:当处理器等待运算结果(比如除法) 和二级缓存操作数时,可以执行其他指令 很多程序员热衷于-O2,它是时间效率和代码 大小的折中
编译器能作什么 关键段 ■-O3终极优化 ca包括O2的所有优化 ■关键段( Time-Critical section): 循环展开:软件流水技术,通过展开循环来填满流 ca90%的CPU时间可能用在了10%的代码上,这 水线,循环次数要求在编译时确定 样的代码就是关键段 移动循环不变量 只有优化关键段才能有效地提高性能 把循环体内保持不变的变量移动到循环体外 mainline简单函数 对于对性能要求不高的应用,没有关键段 把简单的函数就地展开 O3会导致可执行程序体积急剧增大 20u7-1 拥试、性能和可扩展性 试.性能和可护展性 提高性能的四种策略 代码优化 ■收集公共表达式 ■使用更好的算法或数据结构(最重 ■用低代价操作代替高代价的 要) ■铺开或删除代码 ■让编译程序做优化(最easy) ■储存需多次使用的中间结果 ■优化关键段(最有效) ■用空间交换时间 ■不影响风格等前提下,调整其他代 ■使用近似值 在某个低级语言里重写代码 2007-1128 试、性能和可扩展性 2007-11-28 测试,性能和可扩展性 提高性能的十二条建议-1 提高性能的十二条建议-2 ■先设计好正确优秀的算法 a在你开始写代码,优化关键段之前,先用 ■使用 Release而不是 Debug模式编译代码 纸和笔把你想到的优化算法写出来,用逻 VC中,从菜单中选择 辑和数学的方法验证它的正确性,也可以 Build->Set Active Configuration 在弹出的对话框中选择Wn32 Release 想一些测试用例 Set Active Proect Configuration 0 在写优化代码的过程中,时时刻刻要注意 Project configurations 你的代码是否是完全按照你设计的算法来 工作的,如果不是,就回到纸和笔上重新 设计算法 ■在GCC编译时使用-○2选项
2007-11-28 测试、性能和可扩展性 37 编译器能作什么 -O3终极优化 Z包括-O2的所有优化 Z循环展开:软件流水技术,通过展开循环来填满流 水线,循环次数要求在编译时确定 Z移动循环不变量: 把循环体内保持不变的变量移动到循环体外 Zinline简单函数: 把简单的函数就地展开 -O3会导致可执行程序体积急剧增大 2007-11-28 测试、性能和可扩展性 38 关键段 关键段(Time-Critical Section): Z90%的CPU时间可能用在了10%的代码上,这 样的代码就是关键段 Z只有优化关键段才能有效地提高性能 Z对于对性能要求不高的应用,没有关键段 2007-11-28 测试、性能和可扩展性 39 提高性能的四种策略 使用更好的算法或数据结构(最重 要) 让编译程序做优化(最easy) 优化关键段(最有效) 不影响风格等前提下,调整其他代 码 2007-11-28 测试、性能和可扩展性 40 代码优化 收集公共表达式 用低代价操作代替高代价的 铺开或删除代码 储存需多次使用的中间结果 用空间交换时间 使用近似值 在某个低级语言里重写代码 提高性能的十二条建议-1 先设计好正确优秀的算法 Z在你开始写代码,优化关键段之前,先用 纸和笔把你想到的优化算法写出来,用逻 辑和数学的方法验证它的正确性,也可以 想一些测试用例 Z在写优化代码的过程中,时时刻刻要注意 你的代码是否是完全按照你设计的算法来 工作的,如果不是,就回到纸和笔上重新 设计算法 提高性能的十二条建议-2 使用Release而不是Debug模式编译代码 ZVC中,从菜单中选择 Build->Set Active Configuration… 在弹出的对话框中选择Win32 Release 在GCC编译时使用-O2选项
提高性能的十二条建议-3 提高性能的十二条建议-4 ■在 Release:模式时,删除一切调试信息 用记录文件 profiling)的方法找到关键段 for(nt=1;K≤=n++) 在VC中选择菜单 Project> Setting bes=best1]+1;∥假设10时的结果不对 if (i==10&& best(o]l= 26 )cout Profile菜单项生成记录文件 int maino( ■记录文件的结果如下 for(=0,10:计++)for(=0:j<10;j+) FuncAO;∥执行了100次 for(=0,K100;计++)for(j=0j100;j++) →157590115.77590,11000 FuncBI(vod uncB0;∥执行了10000次 .162 0.9 100 FuncA (void ■关键段 FuncT显而易见 提高性能的十二条建议-5 提高性能的十二条建议-6 ■避免在关键段使用依赖于其他进程的变量 ■深入了解在关键段中使用的复杂对象 a对于多进程/线程的程序 a比如,该对象是否有拷贝构造函数? 如果关键段的运行需要另一个进程A来提供一个 a该对象的赋值(-)操作是如何实现的,拷贝还是 量b,那么关键段每次循环都需要A执行一次 引用? 都需要两次进程间切换,而进程切换是相当慢的 a如果是拷贝实现的话,由于拷贝复杂对象很慢 ωa通过合理的设计,把关键段和A放到相同的进程 可以采用引用(&)的方法来避免赋值(=)操作和拷 内,比如可以用不同的线程 贝构造
提高性能的十二条建议-3 在Release模式时,删除一切调试信息 for ( int i=1; iSetting… 提高性能的十二条建议-4 测试程序如下 int main() { int i, j; for ( i=0; iProfile菜单项生成记录文件 记录文件的结果如下 Func Func+Child Hit Time % Time % Count Function --------------------------------------------------------- 15.775 90.1 15.775 90.1 10000 FuncB(void) 1.567 9.0 17.504 100.0 1 _main 0.162 0.9 0.162 0.9 100 FuncA(void) 关键段FuncB显而易见 提高性能的十二条建议-5 避免在关键段使用依赖于其他进程的变量 Z对于多进程/线程的程序 Z如果关键段的运行需要另一个进程A来提供一个 变量b,那么关键段每次循环都需要A执行一次, 都需要两次进程间切换,而进程切换是相当慢的 Z通过合理的设计,把关键段和A放到相同的进程 内,比如可以用不同的线程 提高性能的十二条建议-6 深入了解在关键段中使用的复杂对象 Z比如,该对象是否有拷贝构造函数? Z该对象的赋值(=)操作是如何实现的,拷贝还是 引用? Z如果是拷贝实现的话,由于拷贝复杂对象很慢, 可以采用引用(&)的方法来避免赋值(=)操作和拷 贝构造
提高性能的十二条建议-7 提高性能的十二条建议-8 ■避免系统调用和动态申请内存 ■只计算必须计算的内容 caDivide (int dividend, int divisor, c如果系统调用或对其他库的调用很费时 发挥创造力来将他们移动到关键段之外 a如果有很多的操作只要商不要余数,可以写两成 个两个函数,一个计算商和余数,另一个只计算 R动态申请内存往往很费时,尽可能提前静 diVide (int dividend, int divisor 态地申请这些内存 int& quotient) 提高性能的十二条建议-9 提高性能的十二条建议-10 ■重复的计算可以只进行一次 采用预处理的方法,提前计算一些重要的 变量,以后用到时可以查表得到 for(int y=0; ysimage height(); y++) for(int X=0: X<image width: X++) for(y=0; y<h; y++)for(x=0; X<w, X++) y'=sin( angle)*x+cos( angle)*y;∥旋转变換 高度和宽度可以只算一次 ARCOS和sin的值被反复计算了,可以预处理 int h= image height 0, w= image width o COSAngle cos(angle), sinAngle sin(angle) for (y=0; y<h; y++) for(y=0; y<h; y++)for(x=0: X<w, x++) for(X=0: X<W, X++) X=COSAngle'x-sinAngle*y, y'= sinAngle*x+ COaNgle *y,∥旋转变换 提高性能的十二条建议-11 提高性能的十二条建议-12 ■在所有适用的数据类型中,选择最简单的 ■避免使用复杂、效率低的对象 a更复杂的数据类型意味着更多的内存占用和更慢 比如STL的 string类虽然可以动态改变长度 的操作 但这种方便是以牺牲某些操作的时间代 ca在可以使用foat时,不用 doubl 价得到的。如果是字符串操作很多的应用 a在可以使用int时,不用foat 假如可以事先知道字符串的最大长度或 ca在可以使用 short时,不用int 可以估界,就使用char[]。 ca在可以用byte,char时,不用 short 在可以使用 unsigned int(short,,char,bye)时 不用 lint int(short,char,byte)
提高性能的十二条建议-7 避免系统调用和动态申请内存 Z如果系统调用或对其他库的调用很费时, 发挥创造力来将他们移动到关键段之外 Z动态申请内存往往很费时,尽可能提前静 态地申请这些内存 提高性能的十二条建议-8 只计算必须计算的内容 ZDivide(int dividend, int divisor, int& quotient, int& remainder); Z如果有很多的操作只要商不要余数,可以写两成 个两个函数,一个计算商和余数,另一个只计算 商 ZDivide(int dividend, int divisor, int& quotient); 提高性能的十二条建议-9 重复的计算可以只进行一次 for (int y=0; y<image.height(); y++) for (int x=0; x<image.width(); x++) // ... Z高度和宽度可以只算一次 int h = image.height (), w = image.width (); for (y=0; y<h; y++) for (x=0; x<w; x++) // ... 提高性能的十二条建议-10 采用预处理的方法,提前计算一些重要的 变量,以后用到时可以查表得到 for (y=0; y<h; y++) for (x=0; x<w; x++) x’ = cos(angle) * x – sin(angle) * y, y’ = sin(angle) * x + cos(angle) * y; // 旋转变换 Zcos和sin的值被反复计算了,可以预处理 cosAngle = cos(angle), sinAngle = sin(angle); for (y=0; y<h; y++) for (x=0; x<w; x++) x’ = cosAngle * x – sinAngle * y, y’ = sinAngle * x + cosAngle * y; // 旋转变换 提高性能的十二条建议-11 在所有适用的数据类型中,选择最简单的 Z更复杂的数据类型意味着更多的内存占用和更慢 的操作 Z在可以使用float时,不用double Z在可以使用int时,不用float Z在可以使用short时,不用int Z在可以用byte、char时,不用short Z在可以使用unsigned int(short, char, byte)时 ,不用int int(short, char, byte) 提高性能的十二条建议-12 避免使用复杂、效率低的对象 Z比如STL的string类虽然可以动态改变长度 ,但这种方便是以牺牲某些操作的时间代 价得到的。如果是字符串操作很多的应用 ,假如可以事先知道字符串的最大长度或 可以估界,就使用char[]
性能总结 可扩展性 为了提高性能将丧失 可读性 可扩展性VS可复用性 a模块化结构 ■可扩展性举例 ca可复用性 可扩展性的要求 可扩展性 ■针对优化性能的努力只能用在关键段上 20u7-1 可扩展性 可复用性 ■可扩展性VS可复用性 ca可复用性:用以前写的代码作为新的软件 的组成部分 应用程序1 应用程序2 模块日 模块B 模块D R可扩展性:基于以前的代码来开发新的软 模块C 模块E 模块F 2007-11-28 可扩展性 为什么要可扩展性 ■举例: ■缺点 扩展的代码更难编写 文档转换程 ca更难维护,尤其在有多个开发组的大系统中 修改 档转换程序 优, a可以方便别人使用 αa可以在自己的其他系统中使用 在一个系统中也可多次使用 207-1128
性能总结 为了提高性能将丧失 Z可读性 Z模块化结构 Z可复用性 Z可扩展性 Z…… 针对优化性能的努力只能用在关键段上 2007-11-28 55 可扩展性 可扩展性 VS 可复用性 可扩展性举例 可扩展性的要求 2007-11-28 56 可扩展性 可扩展性 VS 可复用性 Z可复用性:用以前写的代码作为新的软件 的组成部分 Z可扩展性:基于以前的代码来开发新的软 件 可复用性 2007-11-28 58 应用程序1 模块A 模块B 模块C 应用程序2 模块B 模块D 模块E 模块F 可扩展性 2007-11-28 59 文档转换程序 A 文档转换程序 A# 修改 举例: 为什么要可扩展性 缺点: Z可扩展的代码更难编写 Z更难维护,尤其在有多个开发组的大系统中 优点: Z一劳永逸 Z可以方便别人使用 Z可以在自己的其他系统中使用 Z在一个系统中也可多次使用