同一份逻辑,不同人的实现的代码性能会出现数量级的差异; 同一份代码,你可能微调几个字符或者某行代码的顺序,就会有数倍的性能提升;同一份代码,也可能在不同处理器上运行也会有几倍的性能差异;十倍程序员不是只存在于传说中,可能在我们的周围也比比皆是。十倍体现在程序员的方法面面,而代码性能却是其中最直观的一面。

“如何写出高性能代码”系列源自我在组内做的一次分享,本系列将以我个人之前的经验为基础,尝试帮助大家写出更高性能的代码 。原ppt分享的面有宽也比较浅薄,所以这里将原ppt拆分成5个独立的部分,分别成文,也作为对原ppt的扩展和补充,本文是第一篇——善用算法和数据结构。

荀子-劝学中说道:君子生非异也,善假于物也。其大意是君子的资质跟一般人没什么不同,只是善于借助外物罢了。 对于程序猿而已,我们在日常编码过程中,可能最常用的就是数据结构。现代各语言的开发库里基本上都封装好了各类的数据结构,我们基本不需要自己去实现。但错误地使用数据结构可能导致代码性能出现大幅的下降。

这里我举三个Java中因未考虑到底层实现导致性能损耗的示例。

上面这段代码本身功能上没有任何问题,但Java中ArrayList在添加过程中在容量不足时会触发扩容,扩容的过程会额外消耗CPU资源。但我在上述代码中指定了ArrayList的初始化容量为100后,用JMH压测发现有了33%的性能提升。

在Java中,很多容器都有动态扩容的特性,而扩容的过程涉及到内存的拷贝,很消耗性能。 所以建议如果能预知到数据量大小,在容器初始化的时候给定一个初始容量。这点在现在很多公司的编码规范中也明确提出了,如下图来自阿里巴巴Java开发手册。

再来看一个错误使用LinkedList导致的性能问题。

    // jdk LinkedList中的get(int index)public E get(int index) {checkElementIndex(index);return node(index).item;}Node<E> node(int index) {// assert isElementIndex(index);if (index < (size >> 1)) {Node<E> x = first;// 这里会从前到后遍历链表for (int i = 0; i < index; i++)x = x.next;return x;} else {Node<E> x = last;for (int i = size - 1; i > index; i--)x = x.prev;return x;}}

LinkedList并不受动态扩容的影响,但是它的底层实现是用的链表,而链表最大的问题在于不支持随机遍历,所以LinkedList中get(int index)的底层实现是用了遍历,时间复杂度是O(n),而ArrayList的底层实现是数组,它的get时间复杂度是O(1)。在上述代码中我将LinkedList改成ArrayList后压测确实也得到了十倍以上的性能提升。

  在Java中,Set和List都提供了contains()方法,其作用就是校验某个在是否存在于这个集合中,但其contains实现方法完全不一样。在HashSet中,contains直接是从hash表中查找,其时间复杂度只有O(1)。而在ArrayList和LinkedList中,都是需要遍历一次全量数据才能得出结果,时间复杂度是O(n),代码这里就不再赘述,具体可以自行查阅。
  在我实际测试是,Set和List的contains性能差异确实也非常明显。我用JMH测试发现,当有100个元素时,HashSet.contains的性能是ArrayList的10倍,是LinkedList的20倍,当数据量更大时,这个差异会更明显。

以上3个错误的示例其实在我们日常代码中经常会遇到,或许你现在去翻阅下项目代码,很容易就能找到List和Set使用不当之处。 也许你会反驳,JDK中这些Api的性能都极高,而且这部分也只是业务逻辑中非常非常小的一部分,错误得使用可能只会导致整体百分之一甚至千分之一的差异,但是不积跬步无以至千里,不积小流无以成江河。

下图是各种常用数据结构各种操作的时间、空间复杂度供大家查阅:

  算法和数据结构是一个程序员的根基,虽然日常我们很少自己去实现某种具体的算法或数据结构,但我们却无时无刻不在使用各种已被封装好的算法或数据结构,我们应当做到对各种算法和数据结构烂熟于心,包括其时间复杂度、空间复杂度、适用范围。

如何写出高性能代码系列文章

  • (一)善用算法和数据结构
  • (二)巧用数据特性
  • (三)优化内存回收(GC)
  • (四)优化数据访问

如何写出高性能代码(一)善用算法和数据结构相关推荐

  1. 如何写出高性能代码(四)优化数据访问

      同一份逻辑,不同人的实现的代码性能会出现数量级的差异: 同一份代码,你可能微调几个字符或者某行代码的顺序,就会有数倍的性能提升:同一份代码,也可能在不同处理器上运行也会有几倍的性能差异:十倍程序员 ...

  2. 如何写出高性能代码(二)巧用数据特性

    导语 同一份逻辑,不同人的实现的代码性能会出现数量级的差异: 同一份代码,你可能微调几个字符或者某行代码的顺序,就会有数倍的性能提升:同一份代码,也可能在不同处理器上运行也会有几倍的性能差异:十倍程序 ...

  3. 怎样用 Android Annotations 写出高性能代码

    上一篇博文中简单介绍了 Android Annotations 的基本用法,顺便扯了一下概念 - 契约编程,阅读量少的可怜,看来并没有多少人对此感兴趣,今天再来一篇,介绍几个稍微高级点的用法,我就不信 ...

  4. 三周写出高性能的Python代码,这些小技巧你值得一试。

    1一个不上进的 Python 使用者 我是一个有 C 语言背景的开发者.最近转做了 Python,平时用 Python 还算 6,这周在给新员工分享工作之后,有个小孩跑来问我:"哥,你是学 ...

  5. code blocks代码性能分析_Julia系列教程13--如果写出高性能的Julia代码

    避免全局变量https://www.zhihu.com/video/1113506985873588224 code generationhttps://www.zhihu.com/video/111 ...

  6. 写出TREE-PREDECESSOR的伪代码(算法导论第三版12.2-3)

    写出TREE-PREDECESSOR的伪代码(算法导论第三版12.2-3) TREE-PREDECESSOR(x)if x.left != NILreturn TREE-MAXIMUM(x.left) ...

  7. 如何写出“简单“代码?

    如何写出"简单"代码? 当你做实际开发中,你一定会发现有人跟你说,或者你在网上看:要写简单代码要写简单代码.    这句话其实就跟大家熟悉的设计模式中的简单(kiss)原则是挂钩的 ...

  8. 2013年图灵奖得主Leslie Lamport:如何写出数学上完美的算法

    来源:新智元 本文约3100字,建议阅读6分钟 对程序员而言,对数学思维的强调永远不会过分,要写出好代码,不能惧怕数学. 图灵奖得主.分布式系统先驱.LaTeX之父Leslie Lamport认为,对 ...

  9. 哈哈哈,这个教人写出烂代码的项目在 GitHub 上火了...

    如果说到什么是好代码,我们肯定都能说出一堆规则,例如使用一致的格式和缩进.使用清晰的变量名和方法名.在必要时提供文档与注释.不要过度精简代码等等. 但是对于什么是烂代码,你有比较清晰的认识吗? 在 G ...

最新文章

  1. 前端面试的作品示例_如何回答任何技术面试问题-包括示例
  2. 连自己都不放过?六成应用开发不需要程序员!
  3. 深入理解Redis的持久化机制和原理
  4. 为了缅怀Borland Delphi!!!
  5. 大数据时代数据中心的发展思考
  6. 16.算法调用优先于手写的循环
  7. Quartz调度原理
  8. IOC操作Bean管理注解方式(完全注解开发)
  9. 检测Java对象所占内存大小 (转载)
  10. 报告:代币化资产市值已超200亿美元
  11. VISTA中注册表项LEGACY_****的删除--另一种方法:使用psExec
  12. Linux 命令(74)—— top 命令
  13. windows cmd命令行命令
  14. Rosetta Stone罗塞塔石碑学习语言Win+Mac最新v5.0.37完美破解版+全语言包
  15. Android 水瓶动画,贝塞尔Loading
  16. excel 获取股票价格_股票价格的Excel点图
  17. 操作系统进程完成时间,周转时间,带权周转时间, 平均周转时间, 带权平均周转时间计算
  18. 嫌微信公众号排版太丑?这里让你一步到位
  19. IDEA插件系列(87):Base64 image encoder插件——以base64编码的形式查看图像
  20. 工程流体力学笔记暂记10(动量矩方程)

热门文章

  1. 云服务器怎样帮助零售电商高效工作?
  2. 解决无法定位程序输入点sfmDxGetSwapChainStats于动态链接库d3d9.dll
  3. 算法 64式 16、字符串算法整理
  4. ROS问题(1):如何解决连接不上主机的问题
  5. 倒计时7天!解锁“2022阿里巴巴开源开放周”精彩议程
  6. HTML 基础-11-表单-单选功能和默认选中
  7. goland2020设置go module
  8. 在中秋茶花会上的发言
  9. 阿里图库字体使用方法---新手适合看
  10. 什么是 DNS DKIM 记录?