From e55bf08d98b163e6f94d164fc650d2e427bc9c3b Mon Sep 17 00:00:00 2001 From: Andy Pan Date: Sat, 18 Nov 2023 18:59:51 +0800 Subject: [PATCH] net: support benchmark testing for sendfile on various platforms When I introduced the benchmark test code for sendfile(2) in CL 425878, I only did it on Linux while the sendfile system call is also available on other Unix-like and Windows platforms, this CL will pick up where I left out. goos: darwin goarch: arm64 pkg: net BenchmarkSendFile/file-to-tcp/1024-10 2240488 749.5 ns/op 1366.30 MB/s 0 B/op 0 allocs/op BenchmarkSendFile/file-to-tcp/2048-10 1956669 850.4 ns/op 2408.38 MB/s 0 B/op 0 allocs/op BenchmarkSendFile/file-to-tcp/4096-10 840103 1593 ns/op 2571.30 MB/s 0 B/op 0 allocs/op BenchmarkSendFile/file-to-tcp/8192-10 449536 2881 ns/op 2843.35 MB/s 0 B/op 0 allocs/op BenchmarkSendFile/file-to-tcp/16384-10 269974 6307 ns/op 2597.86 MB/s 0 B/op 0 allocs/op BenchmarkSendFile/file-to-tcp/32768-10 137210 12646 ns/op 2591.09 MB/s 0 B/op 0 allocs/op BenchmarkSendFile/file-to-tcp/65536-10 66642 24557 ns/op 2668.74 MB/s 0 B/op 0 allocs/op BenchmarkSendFile/file-to-tcp/131072-10 37852 59550 ns/op 2201.03 MB/s 0 B/op 0 allocs/op BenchmarkSendFile/file-to-tcp/262144-10 16288 107859 ns/op 2430.44 MB/s 2 B/op 0 allocs/op BenchmarkSendFile/file-to-tcp/524288-10 10540 249957 ns/op 2097.52 MB/s 3 B/op 0 allocs/op BenchmarkSendFile/file-to-tcp/1048576-10 4982 419750 ns/op 2498.09 MB/s 6 B/op 0 allocs/op BenchmarkSendFile/file-to-unix/1024-10 1180185 1187 ns/op 862.66 MB/s 0 B/op 0 allocs/op BenchmarkSendFile/file-to-unix/2048-10 523159 2294 ns/op 892.78 MB/s 0 B/op 0 allocs/op BenchmarkSendFile/file-to-unix/4096-10 238792 5223 ns/op 784.29 MB/s 0 B/op 0 allocs/op BenchmarkSendFile/file-to-unix/8192-10 116611 10929 ns/op 749.58 MB/s 0 B/op 0 allocs/op BenchmarkSendFile/file-to-unix/16384-10 57568 19870 ns/op 824.57 MB/s 0 B/op 0 allocs/op BenchmarkSendFile/file-to-unix/32768-10 32280 33696 ns/op 972.47 MB/s 1 B/op 0 allocs/op BenchmarkSendFile/file-to-unix/65536-10 17242 72122 ns/op 908.69 MB/s 1 B/op 0 allocs/op BenchmarkSendFile/file-to-unix/131072-10 8350 159131 ns/op 823.67 MB/s 3 B/op 0 allocs/op BenchmarkSendFile/file-to-unix/262144-10 3872 318000 ns/op 824.35 MB/s 8 B/op 0 allocs/op BenchmarkSendFile/file-to-unix/524288-10 1766 600785 ns/op 872.67 MB/s 18 B/op 0 allocs/op BenchmarkSendFile/file-to-unix/1048576-10 993 1138624 ns/op 920.92 MB/s 33 B/op 0 allocs/op goos: linux goarch: amd64 pkg: net cpu: DO-Premium-AMD BenchmarkSendFile/file-to-tcp/1024-8 1796002 716.3 ns/op 1429.59 MB/s 0 B/op 0 allocs/op BenchmarkSendFile/file-to-tcp/2048-8 1196700 896.6 ns/op 2284.23 MB/s 0 B/op 0 allocs/op BenchmarkSendFile/file-to-tcp/4096-8 923604 2385 ns/op 1717.48 MB/s 0 B/op 0 allocs/op BenchmarkSendFile/file-to-tcp/8192-8 638967 9722 ns/op 842.60 MB/s 0 B/op 0 allocs/op BenchmarkSendFile/file-to-tcp/16384-8 357740 18710 ns/op 875.67 MB/s 0 B/op 0 allocs/op BenchmarkSendFile/file-to-tcp/32768-8 147417 17489 ns/op 1873.66 MB/s 0 B/op 0 allocs/op BenchmarkSendFile/file-to-tcp/65536-8 113054 58818 ns/op 1114.21 MB/s 0 B/op 0 allocs/op BenchmarkSendFile/file-to-tcp/131072-8 57981 113202 ns/op 1157.86 MB/s 0 B/op 0 allocs/op BenchmarkSendFile/file-to-tcp/262144-8 26362 253376 ns/op 1034.61 MB/s 0 B/op 0 allocs/op BenchmarkSendFile/file-to-tcp/524288-8 13767 442053 ns/op 1186.03 MB/s 0 B/op 0 allocs/op BenchmarkSendFile/file-to-tcp/1048576-8 4906 829984 ns/op 1263.37 MB/s 0 B/op 0 allocs/op BenchmarkSendFile/file-to-unix/1024-8 2031691 628.9 ns/op 1628.36 MB/s 0 B/op 0 allocs/op BenchmarkSendFile/file-to-unix/2048-8 1294472 965.0 ns/op 2122.30 MB/s 0 B/op 0 allocs/op BenchmarkSendFile/file-to-unix/4096-8 1005753 1203 ns/op 3404.27 MB/s 0 B/op 0 allocs/op BenchmarkSendFile/file-to-unix/8192-8 865448 6412 ns/op 1277.65 MB/s 0 B/op 0 allocs/op BenchmarkSendFile/file-to-unix/16384-8 268946 12801 ns/op 1279.89 MB/s 0 B/op 0 allocs/op BenchmarkSendFile/file-to-unix/32768-8 153398 6691 ns/op 4897.23 MB/s 0 B/op 0 allocs/op BenchmarkSendFile/file-to-unix/65536-8 88911 11969 ns/op 5475.36 MB/s 0 B/op 0 allocs/op BenchmarkSendFile/file-to-unix/131072-8 48639 107538 ns/op 1218.84 MB/s 0 B/op 0 allocs/op BenchmarkSendFile/file-to-unix/262144-8 22720 203199 ns/op 1290.09 MB/s 0 B/op 0 allocs/op BenchmarkSendFile/file-to-unix/524288-8 12034 97126 ns/op 5398.03 MB/s 0 B/op 0 allocs/op BenchmarkSendFile/file-to-unix/1048576-8 5374 202308 ns/op 5183.06 MB/s 0 B/op 0 allocs/op Change-Id: Ib9507bd9837ecb38b1702afa89502da18806929c Reviewed-on: https://go-review.googlesource.com/c/go/+/543276 Reviewed-by: Damien Neil Reviewed-by: Bryan Mills Auto-Submit: Ian Lance Taylor LUCI-TryBot-Result: Go LUCI --- src/net/mockserver_test.go | 118 +++++++++++++++++++ src/net/sendfile_linux_test.go | 86 -------------- src/net/sendfile_test.go | 73 ++++++++++++ src/net/splice_linux_test.go | 209 +++++++-------------------------- 4 files changed, 236 insertions(+), 250 deletions(-) delete mode 100644 src/net/sendfile_linux_test.go diff --git a/src/net/mockserver_test.go b/src/net/mockserver_test.go index 46b2a57321..d4bd16e4c6 100644 --- a/src/net/mockserver_test.go +++ b/src/net/mockserver_test.go @@ -8,8 +8,11 @@ import ( "context" "errors" "fmt" + "internal/testenv" + "log" "os" "path/filepath" + "strconv" "sync" "testing" "time" @@ -506,3 +509,118 @@ func packetTransceiver(c PacketConn, wb []byte, dst Addr, ch chan<- error) { ch <- fmt.Errorf("read %d; want %d", n, len(wb)) } } + +func spawnTestSocketPair(t testing.TB, net string) (client, server Conn) { + t.Helper() + ln := newLocalListener(t, net) + defer ln.Close() + var cerr, serr error + acceptDone := make(chan struct{}) + go func() { + server, serr = ln.Accept() + acceptDone <- struct{}{} + }() + client, cerr = Dial(ln.Addr().Network(), ln.Addr().String()) + <-acceptDone + if cerr != nil { + if server != nil { + server.Close() + } + t.Fatal(cerr) + } + if serr != nil { + if client != nil { + client.Close() + } + t.Fatal(serr) + } + return client, server +} + +func startTestSocketPeer(t testing.TB, conn Conn, op string, chunkSize, totalSize int) (func(t testing.TB), error) { + f, err := conn.(interface{ File() (*os.File, error) }).File() + if err != nil { + return nil, err + } + + cmd := testenv.Command(t, os.Args[0]) + cmd.Env = []string{ + "GO_NET_TEST_TRANSFER=1", + "GO_NET_TEST_TRANSFER_OP=" + op, + "GO_NET_TEST_TRANSFER_CHUNK_SIZE=" + strconv.Itoa(chunkSize), + "GO_NET_TEST_TRANSFER_TOTAL_SIZE=" + strconv.Itoa(totalSize), + "TMPDIR=" + os.Getenv("TMPDIR"), + } + cmd.ExtraFiles = append(cmd.ExtraFiles, f) + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + + if err := cmd.Start(); err != nil { + return nil, err + } + + cmdCh := make(chan error, 1) + go func() { + err := cmd.Wait() + conn.Close() + f.Close() + cmdCh <- err + }() + + return func(tb testing.TB) { + err := <-cmdCh + if err != nil { + tb.Errorf("process exited with error: %v", err) + } + }, nil +} + +func init() { + if os.Getenv("GO_NET_TEST_TRANSFER") == "" { + return + } + defer os.Exit(0) + + f := os.NewFile(uintptr(3), "splice-test-conn") + defer f.Close() + + conn, err := FileConn(f) + if err != nil { + log.Fatal(err) + } + + var chunkSize int + if chunkSize, err = strconv.Atoi(os.Getenv("GO_NET_TEST_TRANSFER_CHUNK_SIZE")); err != nil { + log.Fatal(err) + } + buf := make([]byte, chunkSize) + + var totalSize int + if totalSize, err = strconv.Atoi(os.Getenv("GO_NET_TEST_TRANSFER_TOTAL_SIZE")); err != nil { + log.Fatal(err) + } + + var fn func([]byte) (int, error) + switch op := os.Getenv("GO_NET_TEST_TRANSFER_OP"); op { + case "r": + fn = conn.Read + case "w": + defer conn.Close() + + fn = conn.Write + default: + log.Fatalf("unknown op %q", op) + } + + var n int + for count := 0; count < totalSize; count += n { + if count+chunkSize > totalSize { + buf = buf[:totalSize-count] + } + + var err error + if n, err = fn(buf); err != nil { + return + } + } +} diff --git a/src/net/sendfile_linux_test.go b/src/net/sendfile_linux_test.go deleted file mode 100644 index 7a66d3645f..0000000000 --- a/src/net/sendfile_linux_test.go +++ /dev/null @@ -1,86 +0,0 @@ -// Copyright 2022 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. - -//go:build linux - -package net - -import ( - "io" - "os" - "strconv" - "testing" -) - -func BenchmarkSendFile(b *testing.B) { - b.Run("file-to-tcp", func(b *testing.B) { benchmarkSendFile(b, "tcp") }) - b.Run("file-to-unix", func(b *testing.B) { benchmarkSendFile(b, "unix") }) -} - -func benchmarkSendFile(b *testing.B, proto string) { - for i := 0; i <= 10; i++ { - size := 1 << (i + 10) - bench := sendFileBench{ - proto: proto, - chunkSize: size, - } - b.Run(strconv.Itoa(size), bench.benchSendFile) - } -} - -type sendFileBench struct { - proto string - chunkSize int -} - -func (bench sendFileBench) benchSendFile(b *testing.B) { - fileSize := b.N * bench.chunkSize - f := createTempFile(b, fileSize) - - client, server := spliceTestSocketPair(b, bench.proto) - defer server.Close() - - cleanUp, err := startSpliceClient(client, "r", bench.chunkSize, fileSize) - if err != nil { - client.Close() - b.Fatal(err) - } - defer cleanUp() - - b.ReportAllocs() - b.SetBytes(int64(bench.chunkSize)) - b.ResetTimer() - - // Data go from file to socket via sendfile(2). - sent, err := io.Copy(server, f) - if err != nil { - b.Fatalf("failed to copy data with sendfile, error: %v", err) - } - if sent != int64(fileSize) { - b.Fatalf("bytes sent mismatch, got: %d, want: %d", sent, fileSize) - } -} - -func createTempFile(b *testing.B, size int) *os.File { - f, err := os.CreateTemp(b.TempDir(), "linux-sendfile-bench") - if err != nil { - b.Fatalf("failed to create temporary file: %v", err) - } - b.Cleanup(func() { - f.Close() - }) - - data := make([]byte, size) - if _, err := f.Write(data); err != nil { - b.Fatalf("failed to create and feed the file: %v", err) - } - if err := f.Sync(); err != nil { - b.Fatalf("failed to save the file: %v", err) - } - if _, err := f.Seek(0, io.SeekStart); err != nil { - b.Fatalf("failed to rewind the file: %v", err) - } - - return f -} diff --git a/src/net/sendfile_test.go b/src/net/sendfile_test.go index 4cba1ed2b1..c3d5e714bd 100644 --- a/src/net/sendfile_test.go +++ b/src/net/sendfile_test.go @@ -14,6 +14,7 @@ import ( "io" "os" "runtime" + "strconv" "sync" "testing" "time" @@ -446,3 +447,75 @@ func BenchmarkSendfileZeroBytes(b *testing.B) { cancel() } + +func BenchmarkSendFile(b *testing.B) { + b.Run("file-to-tcp", func(b *testing.B) { benchmarkSendFile(b, "tcp") }) + b.Run("file-to-unix", func(b *testing.B) { benchmarkSendFile(b, "unix") }) +} + +func benchmarkSendFile(b *testing.B, proto string) { + for i := 0; i <= 10; i++ { + size := 1 << (i + 10) + bench := sendFileBench{ + proto: proto, + chunkSize: size, + } + b.Run(strconv.Itoa(size), bench.benchSendFile) + } +} + +type sendFileBench struct { + proto string + chunkSize int +} + +func (bench sendFileBench) benchSendFile(b *testing.B) { + fileSize := b.N * bench.chunkSize + f := createTempFile(b, fileSize) + + client, server := spawnTestSocketPair(b, bench.proto) + defer server.Close() + + cleanUp, err := startTestSocketPeer(b, client, "r", bench.chunkSize, fileSize) + if err != nil { + client.Close() + b.Fatal(err) + } + defer cleanUp(b) + + b.ReportAllocs() + b.SetBytes(int64(bench.chunkSize)) + b.ResetTimer() + + // Data go from file to socket via sendfile(2). + sent, err := io.Copy(server, f) + if err != nil { + b.Fatalf("failed to copy data with sendfile, error: %v", err) + } + if sent != int64(fileSize) { + b.Fatalf("bytes sent mismatch, got: %d, want: %d", sent, fileSize) + } +} + +func createTempFile(b *testing.B, size int) *os.File { + f, err := os.CreateTemp(b.TempDir(), "sendfile-bench") + if err != nil { + b.Fatalf("failed to create temporary file: %v", err) + } + b.Cleanup(func() { + f.Close() + }) + + data := make([]byte, size) + if _, err := f.Write(data); err != nil { + b.Fatalf("failed to create and feed the file: %v", err) + } + if err := f.Sync(); err != nil { + b.Fatalf("failed to save the file: %v", err) + } + if _, err := f.Seek(0, io.SeekStart); err != nil { + b.Fatalf("failed to rewind the file: %v", err) + } + + return f +} diff --git a/src/net/splice_linux_test.go b/src/net/splice_linux_test.go index 7082ecdfbe..2edd744406 100644 --- a/src/net/splice_linux_test.go +++ b/src/net/splice_linux_test.go @@ -9,14 +9,11 @@ package net import ( "internal/poll" "io" - "log" "os" - "os/exec" "strconv" "sync" "syscall" "testing" - "time" ) func TestSplice(t *testing.T) { @@ -62,30 +59,33 @@ type spliceTestCase struct { func (tc spliceTestCase) test(t *testing.T) { hook := hookSplice(t) - clientUp, serverUp := spliceTestSocketPair(t, tc.upNet) + // We need to use the actual size for startTestSocketPeer when testing with LimitedReader, + // otherwise the child process created in startTestSocketPeer will hang infinitely because of + // the mismatch of data size to transfer. + size := tc.totalSize + if tc.limitReadSize > 0 { + if tc.limitReadSize < size { + size = tc.limitReadSize + } + } + + clientUp, serverUp := spawnTestSocketPair(t, tc.upNet) defer serverUp.Close() - cleanup, err := startSpliceClient(clientUp, "w", tc.chunkSize, tc.totalSize) + cleanup, err := startTestSocketPeer(t, clientUp, "w", tc.chunkSize, size) if err != nil { t.Fatal(err) } - defer cleanup() - clientDown, serverDown := spliceTestSocketPair(t, tc.downNet) + defer cleanup(t) + clientDown, serverDown := spawnTestSocketPair(t, tc.downNet) defer serverDown.Close() - cleanup, err = startSpliceClient(clientDown, "r", tc.chunkSize, tc.totalSize) + cleanup, err = startTestSocketPeer(t, clientDown, "r", tc.chunkSize, size) if err != nil { t.Fatal(err) } - defer cleanup() + defer cleanup(t) - var ( - r io.Reader = serverUp - size = tc.totalSize - ) + var r io.Reader = serverUp if tc.limitReadSize > 0 { - if tc.limitReadSize < size { - size = tc.limitReadSize - } - r = &io.LimitedReader{ N: int64(tc.limitReadSize), R: serverUp, @@ -167,31 +167,34 @@ func verifySpliceFds(t *testing.T, c Conn, hook *spliceHook, fdType string) { func (tc spliceTestCase) testFile(t *testing.T) { hook := hookSplice(t) + // We need to use the actual size for startTestSocketPeer when testing with LimitedReader, + // otherwise the child process created in startTestSocketPeer will hang infinitely because of + // the mismatch of data size to transfer. + actualSize := tc.totalSize + if tc.limitReadSize > 0 { + if tc.limitReadSize < actualSize { + actualSize = tc.limitReadSize + } + } + f, err := os.OpenFile(os.DevNull, os.O_WRONLY, 0) if err != nil { t.Fatal(err) } defer f.Close() - client, server := spliceTestSocketPair(t, tc.upNet) + client, server := spawnTestSocketPair(t, tc.upNet) defer server.Close() - cleanup, err := startSpliceClient(client, "w", tc.chunkSize, tc.totalSize) + cleanup, err := startTestSocketPeer(t, client, "w", tc.chunkSize, actualSize) if err != nil { client.Close() t.Fatal("failed to start splice client:", err) } - defer cleanup() + defer cleanup(t) - var ( - r io.Reader = server - actualSize = tc.totalSize - ) + var r io.Reader = server if tc.limitReadSize > 0 { - if tc.limitReadSize < actualSize { - actualSize = tc.limitReadSize - } - r = &io.LimitedReader{ N: int64(tc.limitReadSize), R: r, @@ -234,9 +237,9 @@ func testSpliceReaderAtEOF(t *testing.T, upNet, downNet string) { hook := hookSplice(t) - clientUp, serverUp := spliceTestSocketPair(t, upNet) + clientUp, serverUp := spawnTestSocketPair(t, upNet) defer clientUp.Close() - clientDown, serverDown := spliceTestSocketPair(t, downNet) + clientDown, serverDown := spawnTestSocketPair(t, downNet) defer clientDown.Close() defer serverDown.Close() @@ -343,10 +346,10 @@ func testSpliceIssue25985(t *testing.T, upNet, downNet string) { } func testSpliceNoUnixpacket(t *testing.T) { - clientUp, serverUp := spliceTestSocketPair(t, "unixpacket") + clientUp, serverUp := spawnTestSocketPair(t, "unixpacket") defer clientUp.Close() defer serverUp.Close() - clientDown, serverDown := spliceTestSocketPair(t, "tcp") + clientDown, serverDown := spawnTestSocketPair(t, "tcp") defer clientDown.Close() defer serverDown.Close() // If splice called poll.Splice here, we'd get err == syscall.EINVAL @@ -374,7 +377,7 @@ func testSpliceNoUnixgram(t *testing.T) { t.Fatal(err) } defer up.Close() - clientDown, serverDown := spliceTestSocketPair(t, "tcp") + clientDown, serverDown := spawnTestSocketPair(t, "tcp") defer clientDown.Close() defer serverDown.Close() // Analogous to testSpliceNoUnixpacket. @@ -409,23 +412,23 @@ func (tc spliceTestCase) bench(b *testing.B) { // To benchmark the genericReadFrom code path, set this to false. useSplice := true - clientUp, serverUp := spliceTestSocketPair(b, tc.upNet) + clientUp, serverUp := spawnTestSocketPair(b, tc.upNet) defer serverUp.Close() - cleanup, err := startSpliceClient(clientUp, "w", tc.chunkSize, tc.chunkSize*b.N) + cleanup, err := startTestSocketPeer(b, clientUp, "w", tc.chunkSize, tc.chunkSize*b.N) if err != nil { b.Fatal(err) } - defer cleanup() + defer cleanup(b) - clientDown, serverDown := spliceTestSocketPair(b, tc.downNet) + clientDown, serverDown := spawnTestSocketPair(b, tc.downNet) defer serverDown.Close() - cleanup, err = startSpliceClient(clientDown, "r", tc.chunkSize, tc.chunkSize*b.N) + cleanup, err = startTestSocketPeer(b, clientDown, "r", tc.chunkSize, tc.chunkSize*b.N) if err != nil { b.Fatal(err) } - defer cleanup() + defer cleanup(b) b.SetBytes(int64(tc.chunkSize)) b.ResetTimer() @@ -446,128 +449,6 @@ func (tc spliceTestCase) bench(b *testing.B) { } } -func spliceTestSocketPair(t testing.TB, net string) (client, server Conn) { - t.Helper() - ln := newLocalListener(t, net) - defer ln.Close() - var cerr, serr error - acceptDone := make(chan struct{}) - go func() { - server, serr = ln.Accept() - acceptDone <- struct{}{} - }() - client, cerr = Dial(ln.Addr().Network(), ln.Addr().String()) - <-acceptDone - if cerr != nil { - if server != nil { - server.Close() - } - t.Fatal(cerr) - } - if serr != nil { - if client != nil { - client.Close() - } - t.Fatal(serr) - } - return client, server -} - -func startSpliceClient(conn Conn, op string, chunkSize, totalSize int) (func(), error) { - f, err := conn.(interface{ File() (*os.File, error) }).File() - if err != nil { - return nil, err - } - - cmd := exec.Command(os.Args[0], os.Args[1:]...) - cmd.Env = []string{ - "GO_NET_TEST_SPLICE=1", - "GO_NET_TEST_SPLICE_OP=" + op, - "GO_NET_TEST_SPLICE_CHUNK_SIZE=" + strconv.Itoa(chunkSize), - "GO_NET_TEST_SPLICE_TOTAL_SIZE=" + strconv.Itoa(totalSize), - "TMPDIR=" + os.Getenv("TMPDIR"), - } - cmd.ExtraFiles = append(cmd.ExtraFiles, f) - cmd.Stdout = os.Stdout - cmd.Stderr = os.Stderr - - if err := cmd.Start(); err != nil { - return nil, err - } - - donec := make(chan struct{}) - go func() { - cmd.Wait() - conn.Close() - f.Close() - close(donec) - }() - - return func() { - select { - case <-donec: - case <-time.After(5 * time.Second): - log.Printf("killing splice client after 5 second shutdown timeout") - cmd.Process.Kill() - select { - case <-donec: - case <-time.After(5 * time.Second): - log.Printf("splice client didn't die after 10 seconds") - } - } - }, nil -} - -func init() { - if os.Getenv("GO_NET_TEST_SPLICE") == "" { - return - } - defer os.Exit(0) - - f := os.NewFile(uintptr(3), "splice-test-conn") - defer f.Close() - - conn, err := FileConn(f) - if err != nil { - log.Fatal(err) - } - - var chunkSize int - if chunkSize, err = strconv.Atoi(os.Getenv("GO_NET_TEST_SPLICE_CHUNK_SIZE")); err != nil { - log.Fatal(err) - } - buf := make([]byte, chunkSize) - - var totalSize int - if totalSize, err = strconv.Atoi(os.Getenv("GO_NET_TEST_SPLICE_TOTAL_SIZE")); err != nil { - log.Fatal(err) - } - - var fn func([]byte) (int, error) - switch op := os.Getenv("GO_NET_TEST_SPLICE_OP"); op { - case "r": - fn = conn.Read - case "w": - defer conn.Close() - - fn = conn.Write - default: - log.Fatalf("unknown op %q", op) - } - - var n int - for count := 0; count < totalSize; count += n { - if count+chunkSize > totalSize { - buf = buf[:totalSize-count] - } - - var err error - if n, err = fn(buf); err != nil { - return - } - } -} - func BenchmarkSpliceFile(b *testing.B) { b.Run("tcp-to-file", func(b *testing.B) { benchmarkSpliceFile(b, "tcp") }) b.Run("unix-to-file", func(b *testing.B) { benchmarkSpliceFile(b, "unix") }) @@ -598,15 +479,15 @@ func (bench spliceFileBench) benchSpliceFile(b *testing.B) { totalSize := b.N * bench.chunkSize - client, server := spliceTestSocketPair(b, bench.proto) + client, server := spawnTestSocketPair(b, bench.proto) defer server.Close() - cleanup, err := startSpliceClient(client, "w", bench.chunkSize, totalSize) + cleanup, err := startTestSocketPeer(b, client, "w", bench.chunkSize, totalSize) if err != nil { client.Close() b.Fatalf("failed to start splice client: %v", err) } - defer cleanup() + defer cleanup(b) b.ReportAllocs() b.SetBytes(int64(bench.chunkSize)) -- 2.48.1