github.com/llvm-mirror/llgo@v0.0.0-20190322182713-bf6f0a60fce1/utils/benchcomp/main.go (about)

     1  package main
     2  
     3  import (
     4  	"bufio"
     5  	"debug/elf"
     6  	"debug/macho"
     7  	"fmt"
     8  	"os"
     9  	"path/filepath"
    10  	"sort"
    11  	"strconv"
    12  	"strings"
    13  )
    14  
    15  func symsizes(path string) map[string]float64 {
    16  	m := make(map[string]float64)
    17  	f, err := elf.Open(path)
    18  	if err != nil {
    19  		panic(err.Error())
    20  	}
    21  	syms, err := f.Symbols()
    22  	if err != nil {
    23  		panic(err.Error())
    24  	}
    25  	for _, sym := range syms {
    26  		if sym.Section < elf.SectionIndex(len(f.Sections)) && strings.HasPrefix(f.Sections[sym.Section].Name, ".text") {
    27  			m[sym.Name] = float64(sym.Size)
    28  		}
    29  	}
    30  	return m
    31  }
    32  
    33  type bySectionThenOffset []macho.Symbol
    34  
    35  func (syms bySectionThenOffset) Len() int {
    36  	return len(syms)
    37  }
    38  
    39  func (syms bySectionThenOffset) Less(i, j int) bool {
    40  	if syms[i].Sect < syms[j].Sect {
    41  		return true
    42  	}
    43  	if syms[i].Sect > syms[j].Sect {
    44  		return false
    45  	}
    46  	return syms[i].Value < syms[j].Value
    47  }
    48  
    49  func (syms bySectionThenOffset) Swap(i, j int) {
    50  	syms[i], syms[j] = syms[j], syms[i]
    51  }
    52  
    53  func macho_symsizes(path string) map[string]float64 {
    54  	m := make(map[string]float64)
    55  	f, err := macho.Open(path)
    56  	if err != nil {
    57  		panic(err.Error())
    58  	}
    59  	syms := make([]macho.Symbol, len(f.Symtab.Syms))
    60  	copy(syms, f.Symtab.Syms)
    61  	sort.Sort(bySectionThenOffset(syms))
    62  	for i, sym := range syms {
    63  		if sym.Sect == 0 {
    64  			continue
    65  		}
    66  		var nextOffset uint64
    67  		if i == len(syms)-1 || syms[i+1].Sect != sym.Sect {
    68  			nextOffset = f.Sections[sym.Sect-1].Size
    69  		} else {
    70  			nextOffset = syms[i+1].Value
    71  		}
    72  		m[sym.Name] = float64(nextOffset - sym.Value)
    73  	}
    74  	return m
    75  }
    76  
    77  func benchnums(path, stat string) map[string]float64 {
    78  	m := make(map[string]float64)
    79  
    80  	fh, err := os.Open(path)
    81  	if err != nil {
    82  		panic(err.Error())
    83  	}
    84  
    85  	scanner := bufio.NewScanner(fh)
    86  	for scanner.Scan() {
    87  		elems := strings.Split(scanner.Text(), "\t")
    88  		if !strings.HasPrefix(elems[0], "Benchmark") || len(elems) < 3 {
    89  			continue
    90  		}
    91  		var s string
    92  		for _, elem := range elems[2:] {
    93  			selems := strings.Split(strings.TrimSpace(elem), " ")
    94  			if selems[1] == stat {
    95  				s = selems[0]
    96  			}
    97  		}
    98  		if s != "" {
    99  			ns, err := strconv.ParseFloat(s, 64)
   100  			if err != nil {
   101  				panic(scanner.Text() + " ---- " + err.Error())
   102  			}
   103  			m[elems[0]] = ns
   104  		}
   105  	}
   106  
   107  	if err := scanner.Err(); err != nil {
   108  		panic(err)
   109  	}
   110  
   111  	return m
   112  }
   113  
   114  func ninja_logs(path string) map[string]float64 {
   115  	m := make(map[string]float64)
   116  
   117  	fh, err := os.Open(path)
   118  	if err != nil {
   119  		panic(err.Error())
   120  	}
   121  
   122  	scanner := bufio.NewScanner(fh)
   123  	for scanner.Scan() {
   124  		elems := strings.Split(scanner.Text(), "\t")
   125  		if len(elems) < 4 {
   126  			continue
   127  		}
   128  		begin, err := strconv.ParseInt(elems[0], 10, 64)
   129  		if err != nil {
   130  			continue
   131  		}
   132  		end, err := strconv.ParseInt(elems[1], 10, 64)
   133  		if err != nil {
   134  			panic(err.Error())
   135  		}
   136  		m[elems[3]] = float64(end-begin)
   137  	}
   138  
   139  	return m
   140  }
   141  
   142  func filesizes(root string) map[string]float64 {
   143  	m := make(map[string]float64)
   144  
   145  	err := filepath.Walk(root, func(path string, info os.FileInfo, err error) error {
   146  		if info.Mode().IsRegular() {
   147  			m[path[len(root):]] = float64(info.Size())
   148  		}
   149  		return nil
   150  	})
   151  	if err != nil {
   152  		panic(err.Error())
   153  	}
   154  
   155  	return m
   156  }
   157  
   158  func main() {
   159  	var cmp func(string) map[string]float64
   160  	switch os.Args[1] {
   161  	case "symsizes":
   162  		cmp = symsizes
   163  
   164  	case "macho_symsizes":
   165  		cmp = macho_symsizes
   166  
   167  	case "benchns":
   168  		cmp = func(path string) map[string]float64 {
   169  			return benchnums(path, "ns/op")
   170  		}
   171  
   172  	case "benchallocs":
   173  		cmp = func(path string) map[string]float64 {
   174  			return benchnums(path, "allocs/op")
   175  		}
   176  
   177  	case "ninja_logs":
   178  		cmp = ninja_logs
   179  
   180  	case "filesizes":
   181  		cmp = filesizes
   182  	}
   183  
   184  	syms1 := cmp(os.Args[2])
   185  	syms2 := cmp(os.Args[3])
   186  
   187  	for n, z1 := range syms1 {
   188  		if z2, ok := syms2[n]; ok && z2 != 0 {
   189  			fmt.Printf("%s %f %f %f\n", n, z1, z2, z1/z2)
   190  		}
   191  	}
   192  }