diff --git a/src/internal/fuzz/mutator_test.go b/src/internal/fuzz/mutator_test.go index b1b5311639..5fcfb27c16 100644 --- a/src/internal/fuzz/mutator_test.go +++ b/src/internal/fuzz/mutator_test.go @@ -5,11 +5,17 @@ package fuzz import ( + "fmt" + "os" "strconv" "testing" ) func BenchmarkMutatorBytes(b *testing.B) { + origEnv := os.Getenv("GODEBUG") + defer func() { os.Setenv("GODEBUG", origEnv) }() + os.Setenv("GODEBUG", fmt.Sprintf("%s,fuzzseed=123", origEnv)) + for _, size := range []int{ 1, 10, @@ -20,10 +26,74 @@ func BenchmarkMutatorBytes(b *testing.B) { } { size := size b.Run(strconv.Itoa(size), func(b *testing.B) { - vals := []interface{}{make([]byte, size)} - m := newMutator() + buf := make([]byte, size) + b.ResetTimer() + for i := 0; i < b.N; i++ { - m.mutate(vals, workerSharedMemSize) + // resize buffer to the correct shape and reset the PCG + buf = buf[0:size] + m := newMutator() + m.mutate([]interface{}{buf}, workerSharedMemSize) + } + }) + } +} + +func BenchmarkMutatorString(b *testing.B) { + origEnv := os.Getenv("GODEBUG") + defer func() { os.Setenv("GODEBUG", origEnv) }() + os.Setenv("GODEBUG", fmt.Sprintf("%s,fuzzseed=123", origEnv)) + + for _, size := range []int{ + 1, + 10, + 100, + 1000, + 10000, + 100000, + } { + size := size + b.Run(strconv.Itoa(size), func(b *testing.B) { + buf := make([]byte, size) + b.ResetTimer() + + for i := 0; i < b.N; i++ { + // resize buffer to the correct shape and reset the PCG + buf = buf[0:size] + m := newMutator() + m.mutate([]interface{}{string(buf)}, workerSharedMemSize) + } + }) + } +} + +func BenchmarkMutatorAllBasicTypes(b *testing.B) { + origEnv := os.Getenv("GODEBUG") + defer func() { os.Setenv("GODEBUG", origEnv) }() + os.Setenv("GODEBUG", fmt.Sprintf("%s,fuzzseed=123", origEnv)) + + types := []interface{}{ + []byte(""), + string(""), + false, + float32(0), + float64(0), + int(0), + int8(0), + int16(0), + int32(0), + int64(0), + uint8(0), + uint16(0), + uint32(0), + uint64(0), + } + + for _, t := range types { + b.Run(fmt.Sprintf("%T", t), func(b *testing.B) { + for i := 0; i < b.N; i++ { + m := newMutator() + m.mutate([]interface{}{t}, workerSharedMemSize) } }) } diff --git a/src/internal/fuzz/worker_test.go b/src/internal/fuzz/worker_test.go new file mode 100644 index 0000000000..10d61b19db --- /dev/null +++ b/src/internal/fuzz/worker_test.go @@ -0,0 +1,42 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package fuzz + +import ( + "context" + "fmt" + "os" + "testing" +) + +func BenchmarkWorkerFuzzOverhead(b *testing.B) { + origEnv := os.Getenv("GODEBUG") + defer func() { os.Setenv("GODEBUG", origEnv) }() + os.Setenv("GODEBUG", fmt.Sprintf("%s,fuzzseed=123", origEnv)) + + ws := &workerServer{ + fuzzFn: func(_ CorpusEntry) error { return nil }, + workerComm: workerComm{memMu: make(chan *sharedMem, 1)}, + } + + mem, err := sharedMemTempFile(workerSharedMemSize) + if err != nil { + b.Fatalf("failed to create temporary shared memory file: %s", err) + } + + initialVal := []interface{}{make([]byte, 32)} + encodedVals := marshalCorpusFile(initialVal...) + mem.setValue(encodedVals) + + ws.memMu <- mem + + b.ResetTimer() + for i := 0; i < b.N; i++ { + ws.m = newMutator() + mem.setValue(encodedVals) + + ws.fuzz(context.Background(), fuzzArgs{Limit: 1}) + } +}