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 }