栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Go语言

Go学习:pprof性能调优

Go语言 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Go学习:pprof性能调优

调优前 代码
package main


func lengthOfNonRepratingSubStr(s string) int {
	lastOccurred := make(map[rune]int)
	start := 0
	maxLen := 0
	for i, ch := range []rune(s) {
		if lastIndex, ok := lastOccurred[ch]; ok && lastIndex >= start {
			start = lastIndex + 1
		}
		if i-start+1 > maxLen {
			maxLen = i - start + 1
		}
		lastOccurred[ch] = i
	}
	return maxLen
}
性能测试
func BenchmarkSubStr(b *testing.B) {
	param := "黑化肥挥发发灰会花飞灰化肥挥发发黑会飞花"
	for i := 0; i < 13; i++ {
		param = param + param
	}
	b.Logf("len(param) = %d",len(param))
	for i := 0; i < b.N; i++ {
		val := lengthOfNonRepratingSubStr(param)
		ans := 8
		if val != ans {
			b.Errorf("lengtyum install graphvizhOfNonRepratingSubStr(%s); 期望值:%d; 实际值: %d", param, ans, val)
		}
	}
}


没有进行调优时,进行性能测试12920060 ns/op;不算特别慢;但是还可以更快!

Graphviz

使用Graphviz和pprof命令分析代码现在的问题;然后有针对性的去优化代码

Graphviz介绍

      Graphviz是贝尔实验室开发的一个开源的工具包,它使用一个特定的DSL(领域特定语言):dot作为脚本语言,然后使用布局引擎来解析此脚本,并完成自动布局.

Graphviz安装

      Graphviz本身是一个绘图工具软件,下载点击地址.如果你是linux,可以用api-get或者yum的方法安装.如果是windows,就在官网下载msi文件安装;无论是linux还是windows,装完后都要设置环境变量.

调优 分析代码


  • 使用到的命令
go test -bench .
go test -bench . -cpuprofile cpu.out
go tool pprof cpu.out
web
优化思路
  • 我们通过命令+Graphviz生成出一张图;这张图的方框有大有小;线有粗有细,方框越大消耗的时间越长,线越粗消耗的时间越长
  • 通过对图片的分析
    • mapaccess2_fast32 0.38s (18.18%) of 0.62s (29.67%)
    • mapassign_fast32 0.39s (18.66%) of 0.57s (27.27%)
    • stringtoslicerune 0.20s (9.57%) of 0.49s (23.44%)
  • 主要是map和把参数转成[]rune消耗比较大;但是我们有utf8字符串传进来,解码是必不可少的,就只能在map上进行优化
优化代码

使用数组代替map;用空间换时间.map里面每个rune塞进去,它要算哈希;要判重;要分配空间;这一系列操作都太慢了;我们使用数组一开始就把空间分配好;使用空间来换时间

func lengthOfNonRepratingSubStr(s string) int {
	lastOccurred := make([]int, 0xffff)
	for i := range lastOccurred {
		lastOccurred[i] = -1
	}
	start := 0
	maxLen := 0
	for i, ch := range []rune(s) {
		if lastIndex := lastOccurred[ch]; lastIndex != -1 && lastIndex >= start {
			start = lastIndex + 1
		}
		if i-start+1 > maxLen {
			maxLen = i - start + 1
		}
		lastOccurred[ch] = i
	}
	return maxLen
}

初步优化,进行性能测试4562497 ns/op;性能提高的非常明显,肉眼可见

再次进行分析


通过对图片进行分析

  • stringtoslicerune 0.35s (16.91%) of 1.17s (56.52%);解码必不可少
  • asyncPreempt 0.02s (0.97%); asyncPreempt异步无需优化
  • makeslice 0 of 0.11s (5.31%); 创建数组花费的时间还可以继续优化;
优化代码

我们把创建数组的动作提到函数外面,把创建数组的动作减少到一次

var lastOccurred = make([]int, 0xffff)

func lengthOfNonRepratingSubStr(s string) int {

	for i := range lastOccurred {
		lastOccurred[i] = -1
	}
	start := 0
	maxLen := 0
	for i, ch := range []rune(s) {
		if lastIndex := lastOccurred[ch]; lastIndex != -1 && lastIndex >= start {
			start = lastIndex + 1
		}
		if i-start+1 > maxLen {
			maxLen = i - start + 1
		}
		lastOccurred[ch] = i
	}
	return maxLen
}


优化后,进行性能测试4140482 ns/op;相比上次性能测试的结果,这次更快了!

再次进行分析


现在对图片进行分析就只剩一个必不可少的解码动作比较耗时,其他的都已经完成了优化!

总结

  • 每次进行优化都要先获取性能数据
  • 然后查看性能数据
  • 再分析慢在哪里
  • 优化代码
  • 最后再获取性能数组;循环往复,直到把代码优化到一个比较满意的地步

总之,调优不是一蹴而就的,需要分析,推理,实践,总结,再分析,最终定位到具体的问题

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/905293.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号