高质量编程学习笔记(下)|青训营笔记

74 阅读3分钟

这是我参与「第五届青训营 」伴学笔记创作活动的第 6 天

 ps:由于最近春节事务较多,走亲访友的,还有实验室布置的任务,所以一直是咕咕鸟,本来打算日更的。本文是对于高质量编程的知识介绍。

1. 简介

 在当代的代码开发中,对于一个企业而言,都有着对代码运行的性能优化的需求。也正是这样的需求才驱动了对于代码运行的性能优化的研究。高质量的代码虽然能完成功能,但是在大规模的部署场景下,仅仅支持正常功能是不够的,还需要尽可能提升代码性能,以达到节约资源成本的目的。在本课关于高质量编程学习中,我们将会从一些简单的性能优化入手,进行对于高质量编程的理解和学习。

2. 性能优化

 对于性能优化而言,首先需要满足的是代码正确可靠并且简洁清晰。而对于性能优化,其是一个综合评估,故而存在时间效率和空间效率对立的情况。

 本文将针对Go语言的特性,介绍与其相关的性能优化建议等。

2.1 性能优化——slice

 对于slice而言,其作为GO中最常用的一种结构,看上去无论声明还是初始化过程都已十分简洁,但其实还有着许多可以优化的地方。

  • slice预分配内存:在使用slice时,我们应当尽可能在使用make()初始化切片时,提供容量信息。因为预分配内存只有一次内存分配,而不预分配内存则会每次涉及到变量的增加就都进行一次内存分配,显而易见的预分配内存效率相比之下更高。
  • slice大内存释放:在已有切片基础上创建切片,不会创建新的底层数组。故而如果原切片较大的话,因为新建小切片在原切片上有引用,导致原切片无法被释放,白白消耗了大量空间。我们可以在创建新的小切片时,使用copy函数指向一个新的底层数组,令原切片不再引用,让内存被垃圾回收。

2.2 性能优化——Map

 对于Map而言,不断地向map添加元素会触发map扩容,所以我们可以提前分配好空间减少内存拷贝和Rehash的消耗。

 用简单的话说就是Map可以通过预分配内存节约时间。

2.3 性能优化——字符串处理

 字符串在实际编程中十分常用,而对于其优化而言,在进行拼接时,strings.Buffer最快,而+拼接最慢,String.Builder以及bytes.Buffer中间相近。

 这是因为字符串在Go中为不可变类型,占用内存大小是固定的。使用+拼接每次需要重新分配内存,而其他底层实现是byte数组,更适合扩容。对于string.Buffer其具有独自的扩容策略,不需要每次拼接重新分配内存。

2.4 性能优化——空结构体

 对于一些情况,我们可以使用空结构体进行性能优化。因为空结构体struct{}实例不占任何内存空间,可以作为各种场景下的占位符使用,以节省资源。

2.5 性能优化——atomic包

 对于一些需要加锁的场景,我们可以用atomic操作代替锁的实现。因为锁的实现是通过操作系统进行的的,属于系统调用。而atomic操作是通过硬件实现,效率比较高。

3.总结

  对于性能优化,最后有以下几点建议:

  • 避免常见的性能陷阱,即可保证大部分程序性能
  • 普通应用代码,不用一味追求程序性能
  • 优化手段越高级越容易出问题
  • 应当在正确可靠、简洁清晰的质量前提下提高程序性能