Closed wtysos11 closed 3 years ago
今天在读代码的时候遇到了一种比较奇怪的求模方式,顺便以此为基础做一下基准测试(毕竟不是什么时候都有机会写基准测试的)
package main import "fmt" var( masks = [65]uint{} ) func getmodByDefault(x int64) int64{ return x%(1<<32) } func getmodByMask(x int64) int64{ return x & int64(masks[32]) } func init(){ for i := uint(0); i <= 64; i++ { masks[i] = (1 << i) - 1 } //遮盖符号,全部为1,1的数量为i-1 } //构建一个Benchmark func main(){ fmt.Println(getmodByDefault(2000)) fmt.Println(getmodByMask(2000)) }
我碰到的就是这个mask数组的求模方式了。经过语义和手算我才能确定这确实是求模(毕竟数电学的不太好)。但为什么要这么去计算呢?我开始认为是不是这么做速度会快一些
package main import ( "math/rand" "strconv" "testing" ) func Test_getmodByMask(t *testing.T) { type args struct { x int64 } tests := []struct { name string args args want int64 }{} for i:=0;i<100;i++{ targetNum := rand.Int63n(1<<62) tests = append(tests, struct { name string args args want int64 }{name: "test"+strconv.Itoa(i), args: args{targetNum}, want: getmodByDefault(targetNum)}) } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if got := getmodByMask(tt.args.x); got != tt.want { t.Errorf("getmodByMask() = %v, want %v", got, tt.want) } }) } } func BenchmarkModDefault(b *testing.B) { for i:=0;i<b.N;i++{ _ = getmodByDefault(rand.Int63n(1<<62)) } } func BenchmarkModByMask(b *testing.B) { for i:=0;i<b.N;i++{ _ = getmodByMask(rand.Int63n(1<<62)) } }
基准测试的运行需要加上go test -bench=.,不然只会执行单元测试。而且这么执行的话会默认执行单元测试,如果不想要执行单元测试可以go test -run=^$
go test -bench=.
go test -run=^$
结果显示两种方式的速度是一样的。这……可能是代码迁移时的区别吧,底层程序员可能会更偏爱位运算之类的?
今天在读代码的时候遇到了一种比较奇怪的求模方式,顺便以此为基础做一下基准测试(毕竟不是什么时候都有机会写基准测试的)
业务代码部分
我碰到的就是这个mask数组的求模方式了。经过语义和手算我才能确定这确实是求模(毕竟数电学的不太好)。但为什么要这么去计算呢?我开始认为是不是这么做速度会快一些
基准测试
基准测试的运行需要加上
go test -bench=.
,不然只会执行单元测试。而且这么执行的话会默认执行单元测试,如果不想要执行单元测试可以go test -run=^$
结果显示两种方式的速度是一样的。这……可能是代码迁移时的区别吧,底层程序员可能会更偏爱位运算之类的?