PdSort
首先介绍三种经典排序算法:插入排序、快速排序与堆排序。
- 插入排序:从左到右遍历,将当前序列的最后一个值插入到合适的位置。
- 快速排序:选定一个pivot,递归地分为两个子序列。
- 堆排序:构造一个堆,每次将根节点与最后一个位置节点交换并重新调整堆。
三种排序算法的复杂度比较:
| 类型 | 快速排序 | 堆排序 | 插入排序 |
|---|---|---|---|
| Best | O(n*logn) | O(n*logn) | O(n) |
| Avg | O(n*logn) | O(n*logn) | O(n^2) |
| Worst | O(n^2) | O(n*logn) | O(n^2) |
对于排序算法的性能,实际场景的benchmark一般是:
- 根据序列元素的排列情况划分: 随机/有序/重复度较高
- 根据序列的长度划分:16/128/1024
直接放结果:
- 插入排序在短序列中速度最快
- 快速排序在其他情况中速度最快
- 堆排序速度与最快的算法差距不大
- 插入排序在有序情况下最快
如何设计一个更好的算法?
先下一层楼梯,再坐一层电梯。
结合三种排序算法的优点:
- 短序列直接插入排序。
- 其他情况下使用快速排序保证整体性能。
- 快排表现不佳时使用堆排序来稳定性能。
重复度较高? partitionEqual
高质量编程与性能优化
高质量编程
- 代码格式:
gofmt与goimports - 注释:代码是最好的注释,注释需要提供代码未表达出的信息
- 命名规范:简洁清晰
- 控制流程:减少嵌套
- 错误与异常处理:error、panic、recover
性能优化建议:
- go有自己的
benchmark test工具,新开一个坑没学。 - slice预分配
- map预分配
- Builder拼接字符串
- 空结构体节省内存 -
set atomic而不是重量级的锁
性能调优实战
使用pprof工具排查:
- CPU
- memory
- 协程
- 锁
- 阻塞
讲了一下各部分的采样原理,这里不记录了。
这是老师代码对应的文章——golang pprof 实战。