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  }