github.com/prattmic/llgo-embedded@v0.0.0-20150820070356-41cfecea0e1e/utils/benchcomp/main.go (about) 1 package main 2 3 import ( 4 "bufio" 5 "debug/elf" 6 "debug/macho" 7 "fmt" 8 "os" 9 "sort" 10 "strconv" 11 "strings" 12 ) 13 14 func symsizes(path string) map[string]float64 { 15 m := make(map[string]float64) 16 f, err := elf.Open(path) 17 if err != nil { 18 panic(err.Error()) 19 } 20 syms, err := f.Symbols() 21 if err != nil { 22 panic(err.Error()) 23 } 24 for _, sym := range syms { 25 if sym.Section < elf.SectionIndex(len(f.Sections)) && f.Sections[sym.Section].Name == ".text" { 26 m[sym.Name] = float64(sym.Size) 27 } 28 } 29 return m 30 } 31 32 type bySectionThenOffset []macho.Symbol 33 34 func (syms bySectionThenOffset) Len() int { 35 return len(syms) 36 } 37 38 func (syms bySectionThenOffset) Less(i, j int) bool { 39 if syms[i].Sect < syms[j].Sect { 40 return true 41 } 42 if syms[i].Sect > syms[j].Sect { 43 return false 44 } 45 return syms[i].Value < syms[j].Value 46 } 47 48 func (syms bySectionThenOffset) Swap(i, j int) { 49 syms[i], syms[j] = syms[j], syms[i] 50 } 51 52 func macho_symsizes(path string) map[string]float64 { 53 m := make(map[string]float64) 54 f, err := macho.Open(path) 55 if err != nil { 56 panic(err.Error()) 57 } 58 syms := make([]macho.Symbol, len(f.Symtab.Syms)) 59 copy(syms, f.Symtab.Syms) 60 sort.Sort(bySectionThenOffset(syms)) 61 for i, sym := range syms { 62 if sym.Sect == 0 { 63 continue 64 } 65 var nextOffset uint64 66 if i == len(syms)-1 || syms[i+1].Sect != sym.Sect { 67 nextOffset = f.Sections[sym.Sect-1].Size 68 } else { 69 nextOffset = syms[i+1].Value 70 } 71 m[sym.Name] = float64(nextOffset - sym.Value) 72 } 73 return m 74 } 75 76 func benchnums(path, stat string) map[string]float64 { 77 m := make(map[string]float64) 78 79 fh, err := os.Open(path) 80 if err != nil { 81 panic(err.Error()) 82 } 83 84 scanner := bufio.NewScanner(fh) 85 for scanner.Scan() { 86 elems := strings.Split(scanner.Text(), "\t") 87 if !strings.HasPrefix(elems[0], "Benchmark") || len(elems) < 3 { 88 continue 89 } 90 var s string 91 for _, elem := range elems[2:] { 92 selems := strings.Split(strings.TrimSpace(elem), " ") 93 if selems[1] == stat { 94 s = selems[0] 95 } 96 } 97 if s != "" { 98 ns, err := strconv.ParseFloat(s, 64) 99 if err != nil { 100 panic(scanner.Text() + " ---- " + err.Error()) 101 } 102 m[elems[0]] = ns 103 } 104 } 105 106 if err := scanner.Err(); err != nil { 107 panic(err) 108 } 109 110 return m 111 } 112 113 func main() { 114 var cmp func(string) map[string]float64 115 switch os.Args[1] { 116 case "symsizes": 117 cmp = symsizes 118 119 case "macho_symsizes": 120 cmp = macho_symsizes 121 122 case "benchns": 123 cmp = func(path string) map[string]float64 { 124 return benchnums(path, "ns/op") 125 } 126 127 case "benchallocs": 128 cmp = func(path string) map[string]float64 { 129 return benchnums(path, "allocs/op") 130 } 131 } 132 133 syms1 := cmp(os.Args[2]) 134 syms2 := cmp(os.Args[3]) 135 136 for n, z1 := range syms1 { 137 if z2, ok := syms2[n]; ok && z2 != 0 { 138 fmt.Printf("%s %f %f %f\n", n, z1, z2, z1/z2) 139 } 140 } 141 }