zoukankan      html  css  js  c++  java
  • [原]代码优化学习笔记

    以下对程序性能优化的相关知识做了总结。应注意的是没有放之四海皆准的方法

    1.策略

    1.1.最重要的原则:尽量少用代码优化

    (1) 相对于精细的代码优化,程序架构、数据结构、算法和细节设计更重要
    (2) 不成熟的代码优化会危及程序的正确性、功能性和可维护性。
    (3) 有时充满技巧的代码不利于编译程序做优化。
    因此,优化前要先确定代码优化的必要性

    1.2.最关键的环节:剖析

    (1) 80/20原则:大部分的时间消耗可能集中在很少数的几个子程序上。
    (2) 消除并不“最热”的热点实际上不能用程序性能得到实质性的提升。不要优化无关紧要的东西。
    (3) 性能问题的很多方面是违反直觉的。
    (4) 经验没有太大帮助。语言、编译器、平台等条件改变时,经验也会过时。

    1.3.代码优化的时机

    (1) 优化应放在整个系统完成后进行。
    (2) 在程序所有功能运转之前难以确定性能的瓶颈。
    (3) 过早优化可能顾此失彼,忽略整个系统全局性的重要优化。
    (4) 过早优化会妨碍对程序其它目标的理解和判断。
    总结一点就是:过早优化的主要缺陷在于缺乏前瞻性

    1.4.代码优化的步骤


    1. 用良好的设计开发软件,使程序易于理解和修改。
    2. 若程序性能无法达到要求:
    a. 保存程序能正确运行的版本。
    b. 剖析系统,找出热点。
    c. 判断性能的拙劣是否源于设计、数据结构或算法上的缺陷,确定是否应做代码优化。如果不是,回到步骤1。
    d. 对瓶颈代码进行调整。
    e. 每次调整后都对性能进行剖析。
    f. 如果调整没有改进代码的性能,回到步骤2所保存的代码。
    3. 重复步骤2。

    1.5.其它原则

    (1) 程序的正确性比运行速度更重要。
    (2) 应尽量使用高效的算法,而不是去优化一个效率低下的算法。
    (3) 尽管大部分优化方法单独看来收效甚微,但累计起来效果惊人。
    (4) 优化应尽可能保持与硬件无关,并且对于其他操作系统是可移植的。不针对特定平台优化程序。
    (5) 优化应使代码易于修改。
    (6) 优化应该使程序性能的提高不小于20%。

    2.技术

    2.1.常见的低效之源

    (1) 输入/输出操作。
    (2) 系统调用,通常会涉及上下文切换。
    (3) 解释型语言。
    (4) 错误。

    2.2.用空间换取时间

    (1) 扩展数据结构:给数据结构增加其他信息或改变结构的内部信息让它访问的更快。
    (2) 用查表代替昂贵函数的计算:提前计算好运行时载入,或只在运行时计算一次。
    (3) 高速缓存:降低经常访问数据的访问成本。
    (4) 惰性求值:直到需要时才会计算某个元素,可避免计算不必要的元素。

    2.3.用时间换取空间

    (1) 压缩:密集存储表示能够通过增加存储和检索所需的时间来降低存储成本。
    (2) 解释程序:通常,使用解释程序能减少表示程序所需的空间,解释程序压缩表示相同的操作序列。

    2.4.存储

    (1) 数组维度尽可能少。
    (2) 尽可能减少数组访问。
    (3) 对齐数据源地址。
    (4) 成组进行读写操作。
    (5) 消除数据相关性。
    (6) 同时向存储控制器发送多个查询。
    (7) 请求按不少于32个字节的增量方式读取数据。
    (8) 使用所有经历请求的页面。
    (9) 组合执行存取内存的代码。
    (10) 仅仅在必要时才放问内存。
    (11) 写专用的存储分配程序,考虑采用内存池技术。
    (12) 缓存机制,对输入输出做缓冲。

    2.5.循环

    (1) 移出循环不变量。
    (2) 循环展开。
    (3) 循环合并。
    (4) 循环内部尽量少包含测试条件:合并测试条件,将循环内判断外提,哨兵。
    (5) 减少循环内部的工作。
    (6) 最忙的循环放在最内层。
    (7) 传输驱动的循环展开:成本很高的内部循环中,可通过改变使用的变量消除一些赋值,如:删除赋值i=j,后面的代码将j视为i。

    2.6.逻辑

    (1) 利用代数恒等式,用低价的操作代替高价的,如:用左或右移位实现幂的乘或除;使用加法替代乘法;减少数组元素上的循环迭代。
    (2) 删除公共子表达式。
    (3) 知道答案后立即停止判断。
    (4) 调整判断次序:将廉价的经常成功的判断放在昂贵的很少成功的判断前面。
    (5) 表驱动代替复杂判断:可用查找替代一个小的、有限域中的逻辑函数。

    2.7.过程

    (1) 使用宏或内联函数。
    (2) 利用常见情况:正确处理所有情况,并高效处理常见情况。
    (3) 用迭代改写递归,消除尾递归(通常编译器会做此优化) 。
    (4) 尽可能地利用并发:充分使用基本计算机体系结构的数据总线宽度来计算昂贵的表达式。
    (5) 配对计算:若总是同时计算两个类似的表达式,应放到一个过程中成对地计算。

    2.8.汇编

    (1) 不应将代码优化与汇编实现混为一谈。检测到热点后,首先应尽量在高级语言中采取可能的步骤。
    (2) 在用汇编重写代码前,先估算编译器生成汇编代码的效率。改善由编译器生成代码的性能比从零开始用汇编实现要容易得多。
    (3) 如果编译器生成的汇编代码虽然显得很不错,但运行起来仍很慢,可考虑加载到反汇编工具中。
    (4) 如果可用的处理器指令能实现比较高效的算法,可直接着手实现汇编代码。
    (5) 在开发汇编代码时,不管存在什么样的干扰,都应给出一个精巧而高效的方案。
    (6) 应将所有汇编函数存放在单独的模块中。避免使用内联汇编函数,这些函数很少是可移植的,且移植时经常会带来负面效果。

    2.9.其它

    (1) 数学方法解决问题。
    (2) 使用近似值。
    (3) 避免使用浮点数,尽量使用整数。
    (4) 将8位、16位的循环变量替换为32位的。
    (5) 用memset() 代替初始化数组的循环,用memcpy() 代替拷贝数组的循环。
    (6) 尽量减小数组元素的大小,以减少Cache失效率。
    (7) 循环条件判断式中不要有其它运算:while (i--) {}; --> while (i) { i--; };
    (8) 以行序而不是列序迭代数组。

    3.参考文献

    [1]《代码大全》. Steve McConnell 著, 金戈 等译. 电子工业出版社. p587-645
    [2]《编程矶珠》. Jon Bentley 著, 谢君英 等译. 中国电力出版社
    [3]《代码优化:有效使用内存》.  Kris Kaspersky 著, 谭明金 译. 电子工业出版社
    [4]《C代码优化方案》. 王全明整理. 网上资料
    [5] VTune帮助文档

    未完待补充,假如还有机会的话。。。
  • 相关阅读:
    数据中心基础
    云计算基础
    C++ 沉思录 ——句柄——智能指针改写
    Linux 网卡驱动相关——02
    读书笔记(三):【SQL Server 2005 Performance Tuning性能调校】(1):【性能调校概观】
    SQL Server 索引中include的魅力(具有包含性列的索引)
    Flex编程
    ZedGraph使用经验
    Firefox 扩展插件推荐
    读书笔记(三):【SQL Server 2005 Performance Tuning性能调校】(0):【开篇】
  • 原文地址:https://www.cnblogs.com/techsunny/p/1120380.html
Copyright © 2011-2022 走看看