Source file src/internal/trace/testdata/testprog/gc-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 GC-heavy program. This is useful for shaking out
     6  // all sorts of corner cases about GC-related ranges.
     7  
     8  //go:build ignore
     9  
    10  package main
    11  
    12  import (
    13  	"log"
    14  	"os"
    15  	"runtime"
    16  	"runtime/debug"
    17  	"runtime/trace"
    18  	"time"
    19  )
    20  
    21  type node struct {
    22  	children [4]*node
    23  	data     [128]byte
    24  }
    25  
    26  func makeTree(depth int) *node {
    27  	if depth == 0 {
    28  		return new(node)
    29  	}
    30  	return &node{
    31  		children: [4]*node{
    32  			makeTree(depth - 1),
    33  			makeTree(depth - 1),
    34  			makeTree(depth - 1),
    35  			makeTree(depth - 1),
    36  		},
    37  	}
    38  }
    39  
    40  func initTree(n *node) {
    41  	if n == nil {
    42  		return
    43  	}
    44  	for i := range n.data {
    45  		n.data[i] = 'a'
    46  	}
    47  	for i := range n.children {
    48  		initTree(n.children[i])
    49  	}
    50  }
    51  
    52  var trees [16]*node
    53  var ballast *[16]*[1024]*node
    54  var sink []*node
    55  
    56  func main() {
    57  	debug.SetMemoryLimit(50 << 20)
    58  
    59  	for i := range trees {
    60  		trees[i] = makeTree(6)
    61  	}
    62  	ballast = new([16]*[1024]*node)
    63  	for i := range ballast {
    64  		ballast[i] = new([1024]*node)
    65  		for j := range ballast[i] {
    66  			ballast[i][j] = &node{
    67  				data: [128]byte{1, 2, 3, 4},
    68  			}
    69  		}
    70  	}
    71  
    72  	procs := runtime.GOMAXPROCS(-1)
    73  	sink = make([]*node, procs)
    74  
    75  	for i := 0; i < procs; i++ {
    76  		i := i
    77  		go func() {
    78  			for {
    79  				sink[i] = makeTree(3)
    80  				for range 5 {
    81  					initTree(sink[i])
    82  					runtime.Gosched()
    83  				}
    84  			}
    85  		}()
    86  	}
    87  	// Increase the chance that we end up starting and stopping
    88  	// mid-GC by only starting to trace after a few milliseconds.
    89  	time.Sleep(5 * time.Millisecond)
    90  
    91  	// Start tracing.
    92  	if err := trace.Start(os.Stdout); err != nil {
    93  		log.Fatalf("failed to start tracing: %v", err)
    94  	}
    95  	defer trace.Stop()
    96  
    97  	// Let the tracing happen for a bit.
    98  	time.Sleep(400 * time.Millisecond)
    99  }
   100  

View as plain text