golang.org/x/net@v0.25.1-0.20240516223405-c87a5b62e243/quic/bench_test.go (about)

     1  // Copyright 2023 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  //go:build go1.21
     6  
     7  package quic
     8  
     9  import (
    10  	"context"
    11  	"fmt"
    12  	"io"
    13  	"math"
    14  	"sync"
    15  	"testing"
    16  )
    17  
    18  // BenchmarkThroughput is based on the crypto/tls benchmark of the same name.
    19  func BenchmarkThroughput(b *testing.B) {
    20  	for size := 1; size <= 64; size <<= 1 {
    21  		name := fmt.Sprintf("%dMiB", size)
    22  		b.Run(name, func(b *testing.B) {
    23  			throughput(b, int64(size<<20))
    24  		})
    25  	}
    26  }
    27  
    28  func throughput(b *testing.B, totalBytes int64) {
    29  	// Same buffer size as crypto/tls's BenchmarkThroughput, for consistency.
    30  	const bufsize = 32 << 10
    31  
    32  	cli, srv := newLocalConnPair(b, &Config{}, &Config{})
    33  
    34  	go func() {
    35  		buf := make([]byte, bufsize)
    36  		for i := 0; i < b.N; i++ {
    37  			sconn, err := srv.AcceptStream(context.Background())
    38  			if err != nil {
    39  				panic(fmt.Errorf("AcceptStream: %v", err))
    40  			}
    41  			if _, err := io.CopyBuffer(sconn, sconn, buf); err != nil {
    42  				panic(fmt.Errorf("CopyBuffer: %v", err))
    43  			}
    44  			sconn.Close()
    45  		}
    46  	}()
    47  
    48  	b.SetBytes(totalBytes)
    49  	buf := make([]byte, bufsize)
    50  	chunks := int(math.Ceil(float64(totalBytes) / float64(len(buf))))
    51  	for i := 0; i < b.N; i++ {
    52  		cconn, err := cli.NewStream(context.Background())
    53  		if err != nil {
    54  			b.Fatalf("NewStream: %v", err)
    55  		}
    56  		closec := make(chan struct{})
    57  		go func() {
    58  			defer close(closec)
    59  			buf := make([]byte, bufsize)
    60  			if _, err := io.CopyBuffer(io.Discard, cconn, buf); err != nil {
    61  				panic(fmt.Errorf("Discard: %v", err))
    62  			}
    63  		}()
    64  		for j := 0; j < chunks; j++ {
    65  			_, err := cconn.Write(buf)
    66  			if err != nil {
    67  				b.Fatalf("Write: %v", err)
    68  			}
    69  		}
    70  		cconn.CloseWrite()
    71  		<-closec
    72  		cconn.Close()
    73  	}
    74  }
    75  
    76  func BenchmarkReadByte(b *testing.B) {
    77  	cli, srv := newLocalConnPair(b, &Config{}, &Config{})
    78  
    79  	var wg sync.WaitGroup
    80  	defer wg.Wait()
    81  
    82  	wg.Add(1)
    83  	go func() {
    84  		defer wg.Done()
    85  		buf := make([]byte, 1<<20)
    86  		sconn, err := srv.AcceptStream(context.Background())
    87  		if err != nil {
    88  			panic(fmt.Errorf("AcceptStream: %v", err))
    89  		}
    90  		for {
    91  			if _, err := sconn.Write(buf); err != nil {
    92  				break
    93  			}
    94  			sconn.Flush()
    95  		}
    96  	}()
    97  
    98  	b.SetBytes(1)
    99  	cconn, err := cli.NewStream(context.Background())
   100  	if err != nil {
   101  		b.Fatalf("NewStream: %v", err)
   102  	}
   103  	cconn.Flush()
   104  	for i := 0; i < b.N; i++ {
   105  		_, err := cconn.ReadByte()
   106  		if err != nil {
   107  			b.Fatalf("ReadByte: %v", err)
   108  		}
   109  	}
   110  	cconn.Close()
   111  }
   112  
   113  func BenchmarkWriteByte(b *testing.B) {
   114  	cli, srv := newLocalConnPair(b, &Config{}, &Config{})
   115  
   116  	var wg sync.WaitGroup
   117  	defer wg.Wait()
   118  
   119  	wg.Add(1)
   120  	go func() {
   121  		defer wg.Done()
   122  		sconn, err := srv.AcceptStream(context.Background())
   123  		if err != nil {
   124  			panic(fmt.Errorf("AcceptStream: %v", err))
   125  		}
   126  		n, err := io.Copy(io.Discard, sconn)
   127  		if n != int64(b.N) || err != nil {
   128  			b.Errorf("server io.Copy() = %v, %v; want %v, nil", n, err, b.N)
   129  		}
   130  	}()
   131  
   132  	b.SetBytes(1)
   133  	cconn, err := cli.NewStream(context.Background())
   134  	if err != nil {
   135  		b.Fatalf("NewStream: %v", err)
   136  	}
   137  	cconn.Flush()
   138  	for i := 0; i < b.N; i++ {
   139  		if err := cconn.WriteByte(0); err != nil {
   140  			b.Fatalf("WriteByte: %v", err)
   141  		}
   142  	}
   143  	cconn.Close()
   144  }
   145  
   146  func BenchmarkStreamCreation(b *testing.B) {
   147  	cli, srv := newLocalConnPair(b, &Config{}, &Config{})
   148  
   149  	go func() {
   150  		for i := 0; i < b.N; i++ {
   151  			sconn, err := srv.AcceptStream(context.Background())
   152  			if err != nil {
   153  				panic(fmt.Errorf("AcceptStream: %v", err))
   154  			}
   155  			sconn.Close()
   156  		}
   157  	}()
   158  
   159  	buf := make([]byte, 1)
   160  	for i := 0; i < b.N; i++ {
   161  		cconn, err := cli.NewStream(context.Background())
   162  		if err != nil {
   163  			b.Fatalf("NewStream: %v", err)
   164  		}
   165  		cconn.Write(buf)
   166  		cconn.Flush()
   167  		cconn.Read(buf)
   168  		cconn.Close()
   169  	}
   170  }