Source file src/internal/trace/testdata/testprog/stress.go

     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  // Tests a many interesting cases (network, syscalls, a little GC, busy goroutines,
     6  // blocked goroutines, LockOSThread, pipes, and GOMAXPROCS).
     7  
     8  //go:build ignore
     9  
    10  package main
    11  
    12  import (
    13  	"log"
    14  	"net"
    15  	"os"
    16  	"runtime"
    17  	"runtime/trace"
    18  	"sync"
    19  	"time"
    20  )
    21  
    22  func main() {
    23  	var wg sync.WaitGroup
    24  	done := make(chan bool)
    25  
    26  	// Create a goroutine blocked before tracing.
    27  	wg.Add(1)
    28  	go func() {
    29  		<-done
    30  		wg.Done()
    31  	}()
    32  
    33  	// Create a goroutine blocked in syscall before tracing.
    34  	rp, wp, err := os.Pipe()
    35  	if err != nil {
    36  		log.Fatalf("failed to create pipe: %v", err)
    37  	}
    38  	defer func() {
    39  		rp.Close()
    40  		wp.Close()
    41  	}()
    42  	wg.Add(1)
    43  	go func() {
    44  		var tmp [1]byte
    45  		rp.Read(tmp[:])
    46  		<-done
    47  		wg.Done()
    48  	}()
    49  	time.Sleep(time.Millisecond) // give the goroutine above time to block
    50  
    51  	if err := trace.Start(os.Stdout); err != nil {
    52  		log.Fatalf("failed to start tracing: %v", err)
    53  	}
    54  	defer trace.Stop()
    55  
    56  	procs := runtime.GOMAXPROCS(10)
    57  	time.Sleep(50 * time.Millisecond) // test proc stop/start events
    58  
    59  	go func() {
    60  		runtime.LockOSThread()
    61  		for {
    62  			select {
    63  			case <-done:
    64  				return
    65  			default:
    66  				runtime.Gosched()
    67  			}
    68  		}
    69  	}()
    70  
    71  	runtime.GC()
    72  	// Trigger GC from malloc.
    73  	n := 512
    74  	for i := 0; i < n; i++ {
    75  		_ = make([]byte, 1<<20)
    76  	}
    77  
    78  	// Create a bunch of busy goroutines to load all Ps.
    79  	for p := 0; p < 10; p++ {
    80  		wg.Add(1)
    81  		go func() {
    82  			// Do something useful.
    83  			tmp := make([]byte, 1<<16)
    84  			for i := range tmp {
    85  				tmp[i]++
    86  			}
    87  			_ = tmp
    88  			<-done
    89  			wg.Done()
    90  		}()
    91  	}
    92  
    93  	// Block in syscall.
    94  	wg.Add(1)
    95  	go func() {
    96  		var tmp [1]byte
    97  		rp.Read(tmp[:])
    98  		<-done
    99  		wg.Done()
   100  	}()
   101  
   102  	// Test timers.
   103  	timerDone := make(chan bool)
   104  	go func() {
   105  		time.Sleep(time.Millisecond)
   106  		timerDone <- true
   107  	}()
   108  	<-timerDone
   109  
   110  	// A bit of network.
   111  	ln, err := net.Listen("tcp", "127.0.0.1:0")
   112  	if err != nil {
   113  		log.Fatalf("listen failed: %v", err)
   114  	}
   115  	defer ln.Close()
   116  	go func() {
   117  		c, err := ln.Accept()
   118  		if err != nil {
   119  			return
   120  		}
   121  		time.Sleep(time.Millisecond)
   122  		var buf [1]byte
   123  		c.Write(buf[:])
   124  		c.Close()
   125  	}()
   126  	c, err := net.Dial("tcp", ln.Addr().String())
   127  	if err != nil {
   128  		log.Fatalf("dial failed: %v", err)
   129  	}
   130  	var tmp [1]byte
   131  	c.Read(tmp[:])
   132  	c.Close()
   133  
   134  	go func() {
   135  		runtime.Gosched()
   136  		select {}
   137  	}()
   138  
   139  	// Unblock helper goroutines and wait them to finish.
   140  	wp.Write(tmp[:])
   141  	wp.Write(tmp[:])
   142  	close(done)
   143  	wg.Wait()
   144  
   145  	runtime.GOMAXPROCS(procs)
   146  }
   147  

View as plain text