对 Go 程序进行可靠的性能测试
for n := 0; n < size; n++ { tree.Put(n, n) } } }) } } 为什么插入的性能是线性的?红黑树的插入性能不是 O(log(n)) 吗? 代码写错了……吧……? name time/op RBTree_PutWrong/size-0-8 检验,直到找到能够使 p 值能 够满足显著性水平,宣称性能得到了提升。 2020 © Changkun Ou · Go 夜读 · 对 Go 程序进行可靠的性能测试 机器过热 29 对结果进行回归,肉眼可见的性能下降 https://github.com/changkun/cgo-benchmarks/tree/master/syscall 总结 2020 © Changkun Ou · stash pop 恢复代码的修改内容,执行测试得到修改后的性能测试结果 ○ 使用 benchstat 对前后测量到的性能测量进行假设检验 ○ 验证结果有效性,例如确认结果的波动,比较随时间推移造成的性能回归等等 2020 © Changkun Ou · Go 夜读 · 对 Go 程序进行可靠的性能测试 进一步阅读的参考文献 ● https://dave.cheney.net/high-perfo0 码力 | 37 页 | 1.23 MB | 1 年前3Hello 算法 1.0.0b1 Golang版
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 154 10. 查找算法 155 10.1. 线性查找 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 155 10.2. 二分查找 次,算法运行时间随着 ? 增大成线性增长。此算法的时间复杂度被称为 「线性阶」。 ‧ 算法 C 中的打印操作需要循环 1000000 次,但运行时间仍与输入数据大小 ? 无关。因此 C 的时间复杂 度和 A 相同,仍为「常数阶」。 // 算法 A 时间复杂度:常数阶 func algorithm_A(n int) { fmt.Println(0) } // 算法 B 时间复杂度:线性阶 func algorithm_B(n 相比直接统计算法运行时间,时间复杂度分析的做法有什么好处呢?以及有什么不足? 时间复杂度可以有效评估算法效率。算法 B 运行时间的增长是线性的,在 ? > 1 时慢于算法 A ,在 ? > 1000000 时慢于算法 C 。实质上,只要输入数据大小 ? 足够大,复杂度为「常数阶」的算法一定优于 「线性阶」的算法,这也正是时间增长趋势的含义。 时间复杂度的推算方法更加简便。在时间复杂度分析中,我们可以将统计「计算操作的运行时间」简化为统计0 码力 | 190 页 | 14.71 MB | 1 年前3Hello 算法 1.0.0b2 Golang版
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 157 10. 查找算法 158 10.1. 线性查找 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 158 10.2. 二分查找 次,算法运行时间随着 ? 增大成线性增长。此算法的时间复杂度被称为 「线性阶」。 ‧ 算法 C 中的打印操作需要循环 1000000 次,但运行时间仍与输入数据大小 ? 无关。因此 C 的时间复杂 度和 A 相同,仍为「常数阶」。 // 算法 A 时间复杂度:常数阶 func algorithm_A(n int) { fmt.Println(0) } // 算法 B 时间复杂度:线性阶 func algorithm_B(n 相比直接统计算法运行时间,时间复杂度分析的做法有什么好处呢?以及有什么不足? 时间复杂度可以有效评估算法效率。算法 B 运行时间的增长是线性的,在 ? > 1 时慢于算法 A ,在 ? > 1000000 时慢于算法 C 。实质上,只要输入数据大小 ? 足够大,复杂度为「常数阶」的算法一定优于 「线性阶」的算法,这也正是时间增长趋势的含义。 时间复杂度的推算方法更加简便。在时间复杂度分析中,我们可以将统计「计算操作的运行时间」简化为统计0 码力 | 202 页 | 15.73 MB | 1 年前3Hello 算法 1.0.0 Golang版
复杂度分析 hello‑algo.com 20 图 2‑1 是该求和函数的流程框图。 图 2‑1 求和函数的流程框图 此求和函数的操作数量与输入数据大小 ? 成正比,或者说成“线性关系”。实际上,时间复杂度描述的就是 这个“线性关系”。相关内容将会在下一节中详细介绍。 2. while 循环 与 for 循环类似,while 循环也是一种实现迭代的方法。在 while 循环中,程序每轮都会先检查条件,如果条 ,给定三个算法 A、B 和 C : // 算法 A 的时间复杂度:常数阶 func algorithm_A(n int) { fmt.Println(0) } // 算法 B 的时间复杂度:线性阶 func algorithm_B(n int) { for i := 0; i < n; i++ { fmt.Println(0) } } // 算法 C 的时间复杂度:常数阶 func A 只有 1 个打印操作,算法运行时间不随着 ? 增大而增长。我们称此算法的时间复杂度为“常数 阶”。 ‧ 算法 B 中的打印操作需要循环 ? 次,算法运行时间随着 ? 增大呈线性增长。此算法的时间复杂度被称 为“线性阶”。 ‧ 算法 C 中的打印操作需要循环 1000000 次,虽然运行时间很长,但它与输入数据大小 ? 无关。因此 C 的时间复杂度和 A 相同,仍为“常数阶”。 图 2‑70 码力 | 382 页 | 17.60 MB | 1 年前3Hello 算法 1.1.0 Go版
是该求和函数的流程框图。 第 2 章 复杂度分析 hello‑algo.com 20 图 2‑1 求和函数的流程框图 此求和函数的操作数量与输入数据大小 ? 成正比,或者说成“线性关系”。实际上,时间复杂度描述的就是 这个“线性关系”。相关内容将会在下一节中详细介绍。 2. while 循环 与 for 循环类似,while 循环也是一种实现迭代的方法。在 while 循环中,程序每轮都会先检查条件,如果条 hello‑algo.com 29 // 算法 A 的时间复杂度:常数阶 func algorithm_A(n int) { fmt.Println(0) } // 算法 B 的时间复杂度:线性阶 func algorithm_B(n int) { for i := 0; i < n; i++ { fmt.Println(0) } } // 算法 C 的时间复杂度:常数阶 func A 只有 1 个打印操作,算法运行时间不随着 ? 增大而增长。我们称此算法的时间复杂度为“常数 阶”。 ‧ 算法 B 中的打印操作需要循环 ? 次,算法运行时间随着 ? 增大呈线性增长。此算法的时间复杂度被称 为“线性阶”。 ‧ 算法 C 中的打印操作需要循环 1000000 次,虽然运行时间很长,但它与输入数据大小 ? 无关。因此 C 的时间复杂度和 A 相同,仍为“常数阶”。 图 2‑70 码力 | 383 页 | 18.48 MB | 1 年前3Hello 算法 1.0.0b4 Golang版
次,算法运行时间随着 ? 增大呈线性增长。此算法的时间复杂度被称 为「线性阶」。 ‧ 算法 C 中的打印操作需要循环 1000000 次,但运行时间仍与输入数据大小 ? 无关。因此 C 的时间复杂 度和 A 相同,仍为「常数阶」。 // 算法 A 时间复杂度:常数阶 func algorithm_A(n int) { fmt.Println(0) } // 算法 B 时间复杂度:线性阶 func algorithm_B(n 相较于直接统计算法运行时间,时间复杂度分析有哪些优势和局限性呢? 时间复杂度能够有效评估算法效率。例如,算法 B 的运行时间呈线性增长,在 ? > 1 时比算法 A 慢,在 ? > 1000000 时比算法 C 慢。事实上,只要输入数据大小 ? 足够大,复杂度为「常数阶」的算法一定优于 「线性阶」的算法,这正是时间增长趋势所表达的含义。 时间复杂度的推算方法更简便。显然,运行平台和计算操作类型都与算法运行时间的增长趋势无关。因此在 i++ { // +1 fmt.Println(a) // +1 2. 复杂度 hello‑algo.com 17 } } ?(?) 是一次函数,说明时间增长趋势是线性的,因此可以得出时间复杂度是线性阶。 我们将线性阶的时间复杂度记为 ?(?) ,这个数学符号称为「大 ? 记号 Big‑? Notation」,表示函数 ?(?) 的「渐近上界 Asymptotic Upper Bound」。0 码力 | 347 页 | 27.40 MB | 1 年前3Hello 算法 1.0.0b5 Golang版
hello‑algo.com 19 图 2‑1 展示了该求和函数的流程框图。 图 2‑1 求和函数的流程框图 此求和函数的操作数量与输入数据大小 ? 成正比,或者说成“线性关系”。实际上,时间复杂度描述的就是 这个“线性关系”。相关内容将会在下一节中详细介绍。 2. while 循环 与 for 循环类似,while 循环也是一种实现迭代的方法。在 while 循环中,程序每轮都会先检查条件,如果条 ,给定三个算法 函数 A、B 和 C : // 算法 A 的时间复杂度:常数阶 func algorithm_A(n int) { fmt.Println(0) } // 算法 B 的时间复杂度:线性阶 func algorithm_B(n int) { for i := 0; i < n; i++ { fmt.Println(0) } } // 算法 C 的时间复杂度:常数阶 func A 只有 1 个打印操作,算法运行时间不随着 ? 增大而增长。我们称此算法的时间复杂度为“常数 阶”。 ‧ 算法 B 中的打印操作需要循环 ? 次,算法运行时间随着 ? 增大呈线性增长。此算法的时间复杂度被称 为“线性阶”。 ‧ 算法 C 中的打印操作需要循环 1000000 次,虽然运行时间很长,但它与输入数据大小 ? 无关。因此 C 的时间复杂度和 A 相同,仍为“常数阶”。 图 2‑70 码力 | 379 页 | 30.70 MB | 1 年前3Hello 算法 1.2.0 简体中文 Go 版
www.hello‑algo.com 20 图 2‑1 是该求和函数的流程框图。 图 2‑1 求和函数的流程框图 此求和函数的操作数量与输入数据大小 ? 成正比,或者说成“线性关系”。实际上,时间复杂度描述的就是 这个“线性关系”。相关内容将会在下一节中详细介绍。 2. while 循环 与 for 循环类似,while 循环也是一种实现迭代的方法。在 while 循环中,程序每轮都会先检查条件,如果条 hello‑algo.com 29 // 算法 A 的时间复杂度:常数阶 func algorithm_A(n int) { fmt.Println(0) } // 算法 B 的时间复杂度:线性阶 func algorithm_B(n int) { for i := 0; i < n; i++ { fmt.Println(0) } } // 算法 C 的时间复杂度:常数阶 func A 只有 1 个打印操作,算法运行时间不随着 ? 增大而增长。我们称此算法的时间复杂度为“常数 阶”。 ‧ 算法 B 中的打印操作需要循环 ? 次,算法运行时间随着 ? 增大呈线性增长。此算法的时间复杂度被称 为“线性阶”。 ‧ 算法 C 中的打印操作需要循环 1000000 次,虽然运行时间很长,但它与输入数据大小 ? 无关。因此 C 的时间复杂度和 A 相同,仍为“常数阶”。 图 2‑70 码力 | 384 页 | 18.49 MB | 10 月前32.1.7 谈如何构建易于拆分的单体应用
library 和main.go等⽂件; 2. 模块间调⽤⽅式的修改;由函数 handler改为rpc handler 总结 第四部分 总结 微服务架构的困境 业务建模 基于gokit⼯程实践 回归⽣活原点: 1. ⼈ 2. 事 3. 物 4. 规则 1. 选择合适的tools 2. 合理的⽬录结构 3. 善⽤interface{} 可扩展的业务架构 = 业务模型 + 合适的架构模型 + 优雅的⼯程实现0 码力 | 27 页 | 13.04 MB | 1 年前32.游戏战中陪伴助手微服务架构设计与应用
缓存功能下沉 - 由重排层也不是业务层存储缓存 - 破坏推荐系统架构,降低复用性 - 裁剪对局历史 - 最多缓存 10 分钟的对局历史 - 不是根本解决方法 - 微服务单体化 - 腾讯文档团队《回归单体成为潮流?腾讯文档如何实现灵活架构切换》 - 更进一步优化:网络 RPC 改为函数调用,同时保留微服务架构 微服务——上线前压测 贵 微服务——火焰图 - 以实验层火焰图为例,业务逻辑仅占0 码力 | 47 页 | 11.10 MB | 1 年前3
共 15 条
- 1
- 2