github.com/rsc/tmp@v0.0.0-20240517235954-6deaab19748b/bigprog/bigprog.go (about)

     1  // Copyright 2018 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  package main
     6  
     7  import (
     8  	"bytes"
     9  	"fmt"
    10  	"io/ioutil"
    11  	"log"
    12  	"os"
    13  	"os/exec"
    14  	"strings"
    15  	"time"
    16  )
    17  
    18  func main() {
    19  	sizes := []int{1000, 2000, 4000, 8000, 16000, 32000, 64000, 128000, 256000}
    20  	cmds := [][]string{
    21  		{"go", "tool", "compile"},
    22  		{"gotype"},
    23  		{"go", "vet"},
    24  		{"gofmt"},
    25  	}
    26  	big := strings.Repeat("1", 1000)
    27  	for _, cmd := range cmds {
    28  		if len(os.Args) > 1 && !strings.Contains(strings.Join(cmd, " "), os.Args[1]) {
    29  			continue
    30  		}
    31  		fmt.Printf("### %s\n\n", strings.Join(cmd, " "))
    32  		lastStrbig := time.Duration(0)
    33  		for _, size := range sizes {
    34  			fmt.Printf("    %10d  int ", size)
    35  			fmt.Printf("%s", runProg(cmd, "package p\nvar x = `1`"+strings.Repeat("+ `1`", size)+"\n"))
    36  			fmt.Printf("  strbal ")
    37  			fmt.Printf("%s", runProg(cmd, "package p\nvar x = "+balance(size, "1")+"\n"))
    38  			fmt.Printf("  strbigbal ")
    39  			fmt.Printf("%s", runProg(cmd, "package p\nvar x = "+balance(size, big)+"\n"))
    40  			fmt.Printf("  str ")
    41  			fmt.Printf("%s", runProg(cmd, "package p\nvar x = 1"+strings.Repeat("+ 1", size)+"\n"))
    42  			if lastStrbig < 100*time.Second {
    43  				fmt.Printf("  strbig  ")
    44  				t := time.Now()
    45  				result := runProg(cmd, "package p\nvar x = `1`"+strings.Repeat("+ `"+big+"`", size)+"\n")
    46  				fmt.Printf("%s", result)
    47  				lastStrbig = time.Since(t)
    48  				if strings.Contains(result, "!") {
    49  					lastStrbig = 1000 * time.Second
    50  				}
    51  			}
    52  			fmt.Printf("\n")
    53  		}
    54  		fmt.Printf("\n")
    55  	}
    56  }
    57  
    58  func balance(n int, s string) string {
    59  	var buf bytes.Buffer
    60  	balanceN(&buf, n+1, s)
    61  	return buf.String()
    62  }
    63  
    64  func balanceN(buf *bytes.Buffer, n int, s string) {
    65  	if n >= 2 {
    66  		buf.WriteString("(")
    67  		balanceN(buf, n/2, s)
    68  		buf.WriteString(" + ")
    69  		balanceN(buf, n-n/2, s)
    70  		buf.WriteString(")")
    71  		return
    72  	}
    73  	buf.WriteString("`")
    74  	buf.WriteString(s)
    75  	buf.WriteString("`")
    76  }
    77  
    78  func runProg(cmd []string, prog string) string {
    79  	err := ioutil.WriteFile("/tmp/bigprog_tmp_.go", []byte(prog), 0666)
    80  	if err != nil {
    81  		log.Fatal(err)
    82  	}
    83  	defer os.Remove("/tmp/bigprog_tmp_.go")
    84  	start := time.Now()
    85  	out, err := exec.Command(cmd[0], append(cmd[1:], "/tmp/bigprog_tmp_.go")...).CombinedOutput()
    86  	if err != nil {
    87  		if bytes.Contains(out, []byte("runtime: goroutine stack exceeds")) {
    88  			return "  stack!"
    89  		}
    90  		if strings.Contains(err.Error(), "signal: killed") || bytes.Contains(out, []byte("signal: killed")) {
    91  			return "sigkill!"
    92  		}
    93  		if bytes.Contains(out, []byte("out of memory")) {
    94  			if bytes.Contains(out, []byte("concatstring")) {
    95  				return "    mem!"
    96  			}
    97  			if bytes.Contains(out, []byte("morestack")) {
    98  				return "  stack!"
    99  			}
   100  		}
   101  		log.Printf("exec: %s\n%s", err, out)
   102  		return "  crash!"
   103  	}
   104  	return fmt.Sprintf("%7.3fs", time.Since(start).Seconds())
   105  }