Go学习:pprof性能调优

Go学习:pprof性能调优,第1张

调优前 代码
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;相比上次性能测试的结果,这次更快了!

再次进行分析


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

总结

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

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

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/994317.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-21
下一篇 2022-05-21

发表评论

登录后才能评论

评论列表(0条)

保存