forked from OSchip/llvm-project
				
			
		
			
				
	
	
		
			142 lines
		
	
	
		
			2.7 KiB
		
	
	
	
		
			Go
		
	
	
	
			
		
		
	
	
			142 lines
		
	
	
		
			2.7 KiB
		
	
	
	
		
			Go
		
	
	
	
package main
 | 
						|
 | 
						|
import (
 | 
						|
	"bufio"
 | 
						|
	"debug/elf"
 | 
						|
	"debug/macho"
 | 
						|
	"fmt"
 | 
						|
	"os"
 | 
						|
	"sort"
 | 
						|
	"strconv"
 | 
						|
	"strings"
 | 
						|
)
 | 
						|
 | 
						|
func symsizes(path string) map[string]float64 {
 | 
						|
	m := make(map[string]float64)
 | 
						|
	f, err := elf.Open(path)
 | 
						|
	if err != nil {
 | 
						|
		panic(err.Error())
 | 
						|
	}
 | 
						|
	syms, err := f.Symbols()
 | 
						|
	if err != nil {
 | 
						|
		panic(err.Error())
 | 
						|
	}
 | 
						|
	for _, sym := range syms {
 | 
						|
		if sym.Section < elf.SectionIndex(len(f.Sections)) && f.Sections[sym.Section].Name == ".text" {
 | 
						|
			m[sym.Name] = float64(sym.Size)
 | 
						|
		}
 | 
						|
	}
 | 
						|
	return m
 | 
						|
}
 | 
						|
 | 
						|
type bySectionThenOffset []macho.Symbol
 | 
						|
 | 
						|
func (syms bySectionThenOffset) Len() int {
 | 
						|
	return len(syms)
 | 
						|
}
 | 
						|
 | 
						|
func (syms bySectionThenOffset) Less(i, j int) bool {
 | 
						|
	if syms[i].Sect < syms[j].Sect {
 | 
						|
		return true
 | 
						|
	}
 | 
						|
	if syms[i].Sect > syms[j].Sect {
 | 
						|
		return false
 | 
						|
	}
 | 
						|
	return syms[i].Value < syms[j].Value
 | 
						|
}
 | 
						|
 | 
						|
func (syms bySectionThenOffset) Swap(i, j int) {
 | 
						|
	syms[i], syms[j] = syms[j], syms[i]
 | 
						|
}
 | 
						|
 | 
						|
func macho_symsizes(path string) map[string]float64 {
 | 
						|
	m := make(map[string]float64)
 | 
						|
	f, err := macho.Open(path)
 | 
						|
	if err != nil {
 | 
						|
		panic(err.Error())
 | 
						|
	}
 | 
						|
	syms := make([]macho.Symbol, len(f.Symtab.Syms))
 | 
						|
	copy(syms, f.Symtab.Syms)
 | 
						|
	sort.Sort(bySectionThenOffset(syms))
 | 
						|
	for i, sym := range syms {
 | 
						|
		if sym.Sect == 0 {
 | 
						|
			continue
 | 
						|
		}
 | 
						|
		var nextOffset uint64
 | 
						|
		if i == len(syms)-1 || syms[i+1].Sect != sym.Sect {
 | 
						|
			nextOffset = f.Sections[sym.Sect-1].Size
 | 
						|
		} else {
 | 
						|
			nextOffset = syms[i+1].Value
 | 
						|
		}
 | 
						|
		m[sym.Name] = float64(nextOffset - sym.Value)
 | 
						|
	}
 | 
						|
	return m
 | 
						|
}
 | 
						|
 | 
						|
func benchnums(path, stat string) map[string]float64 {
 | 
						|
	m := make(map[string]float64)
 | 
						|
 | 
						|
	fh, err := os.Open(path)
 | 
						|
	if err != nil {
 | 
						|
		panic(err.Error())
 | 
						|
	}
 | 
						|
 | 
						|
	scanner := bufio.NewScanner(fh)
 | 
						|
	for scanner.Scan() {
 | 
						|
		elems := strings.Split(scanner.Text(), "\t")
 | 
						|
		if !strings.HasPrefix(elems[0], "Benchmark") || len(elems) < 3 {
 | 
						|
			continue
 | 
						|
		}
 | 
						|
		var s string
 | 
						|
		for _, elem := range elems[2:] {
 | 
						|
			selems := strings.Split(strings.TrimSpace(elem), " ")
 | 
						|
			if selems[1] == stat {
 | 
						|
				s = selems[0]
 | 
						|
			}
 | 
						|
		}
 | 
						|
		if s != "" {
 | 
						|
			ns, err := strconv.ParseFloat(s, 64)
 | 
						|
			if err != nil {
 | 
						|
				panic(scanner.Text() + " ---- " + err.Error())
 | 
						|
			}
 | 
						|
			m[elems[0]] = ns
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	if err := scanner.Err(); err != nil {
 | 
						|
		panic(err)
 | 
						|
	}
 | 
						|
 | 
						|
	return m
 | 
						|
}
 | 
						|
 | 
						|
func main() {
 | 
						|
	var cmp func(string) map[string]float64
 | 
						|
	switch os.Args[1] {
 | 
						|
	case "symsizes":
 | 
						|
		cmp = symsizes
 | 
						|
 | 
						|
	case "macho_symsizes":
 | 
						|
		cmp = macho_symsizes
 | 
						|
 | 
						|
	case "benchns":
 | 
						|
		cmp = func(path string) map[string]float64 {
 | 
						|
			return benchnums(path, "ns/op")
 | 
						|
		}
 | 
						|
 | 
						|
	case "benchallocs":
 | 
						|
		cmp = func(path string) map[string]float64 {
 | 
						|
			return benchnums(path, "allocs/op")
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	syms1 := cmp(os.Args[2])
 | 
						|
	syms2 := cmp(os.Args[3])
 | 
						|
 | 
						|
	for n, z1 := range syms1 {
 | 
						|
		if z2, ok := syms2[n]; ok && z2 != 0 {
 | 
						|
			fmt.Printf("%s %f %f %f\n", n, z1, z2, z1/z2)
 | 
						|
		}
 | 
						|
	}
 | 
						|
}
 |