package gotool import ( "bytes" "io" "testing" ) const performanceDiagnosticSize = 8 << 20 func BenchmarkPerformanceCombinedOutput(b *testing.B) { for _, testCase := range []struct { name string size int chunkSize int }{ {name: "modest", size: 4 << 10, chunkSize: 4 << 10}, {name: "diagnostic-8MiB", size: performanceDiagnosticSize, chunkSize: performanceDiagnosticSize}, {name: "diagnostic-8MiB-32KiB-chunks", size: performanceDiagnosticSize, chunkSize: 32 << 10}, } { input := bytes.Repeat([]byte("go tool diagnostic output\n"), (testCase.size+25)/26) input = input[:testCase.size] b.Run(testCase.name+"/discard-forwarding", func(b *testing.B) { // Verify capture and forwarding for this workload outside the measurement. var forwarded bytes.Buffer verification := &combinedWriter{output: &forwarded} for offset := 0; offset < len(input); offset += testCase.chunkSize { chunk := input[offset:min(offset+testCase.chunkSize, len(input))] if written, err := verification.Write(chunk); err != nil || written != len(chunk) { b.Fatalf("verify output write = %d, err %v; want %d bytes", written, err, len(chunk)) } } if !bytes.Equal(verification.take(), input) || !bytes.Equal(forwarded.Bytes(), input) { b.Fatal("captured and forwarded output must equal the complete input") } b.ReportAllocs() b.SetBytes(int64(len(input))) b.ResetTimer() b.ReportMetric(float64(len(input)), "bytes/op") for i := 0; i < b.N; i++ { writer := &combinedWriter{output: io.Discard} for offset := 0; offset < len(input); offset += testCase.chunkSize { chunk := input[offset:min(offset+testCase.chunkSize, len(input))] if written, err := writer.Write(chunk); err != nil || written != len(chunk) { b.Fatalf("write captured output = %d, err %v; want %d bytes", written, err, len(chunk)) } } captured := writer.take() if len(captured) != len(input) { b.Fatalf("captured output = %d bytes, want %d", len(captured), len(input)) } } }) } }