Skip to content

Instantly share code, notes, and snippets.

@siddontang
Created April 5, 2018 20:52
Show Gist options
  • Save siddontang/8d5e4c8029e5b1df481546063842be91 to your computer and use it in GitHub Desktop.
Save siddontang/8d5e4c8029e5b1df481546063842be91 to your computer and use it in GitHub Desktop.
package main
import (
"bufio"
"bytes"
"fmt"
"os"
"sort"
"strconv"
"strings"
)
func perror(err error) {
if err != nil {
fmt.Printf("%s\n", err)
os.Exit(1)
}
}
type memInfo struct {
addr uint64
buf bytes.Buffer
size uint64
count int
}
type btStat struct {
stack string
size uint64
count int
}
type btStatSlice []*btStat
func (s btStatSlice) Len() int { return len(s) }
func (s btStatSlice) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
func (s btStatSlice) Less(i, j int) bool { return s[i].size < s[j].size }
func getAddr(addrStr string) (uint64, error) {
addrStr = strings.TrimSpace(addrStr)
addrStr = strings.TrimLeft(addrStr, "0x")
return strconv.ParseUint(addrStr, 16, 64)
}
func main() {
stats := make(map[uint64]*memInfo, 100000)
if len(os.Args) != 2 {
perror(fmt.Errorf("need file to be parsed"))
}
name := os.Args[1]
f, err := os.Open(name)
perror(err)
defer f.Close()
scanner := bufio.NewScanner(f)
var m *memInfo
for scanner.Scan() {
line := strings.TrimSpace(scanner.Text())
if strings.HasPrefix(line, "malloc") {
if m != nil {
stats[m.addr] = m
}
items := strings.Split(line, ",")
v1 := strings.Split(items[0], ":")
v2 := strings.Split(items[1], ":")
addr, err := getAddr(v1[1])
perror(err)
size, err := strconv.ParseUint(strings.TrimSpace(v2[1]), 10, 64)
perror(err)
m = new(memInfo)
m.addr = addr
m.size = size
} else if strings.HasPrefix(line, "free") {
items := strings.Split(line, ":")
addr, err := getAddr(items[1])
perror(err)
delete(stats, addr)
} else {
if m != nil {
m.buf.WriteString(line)
m.buf.WriteByte('\n')
}
}
}
perror(scanner.Err())
mapBtStats := make(map[string]*btStat, len(stats))
for _, m := range stats {
stack := m.buf.String()
s, ok := mapBtStats[stack]
if !ok {
s = new(btStat)
s.stack = stack
mapBtStats[stack] = s
}
s.size += m.size
s.count++
}
btStats := make(btStatSlice, 0, len(mapBtStats))
for _, s := range mapBtStats {
btStats = append(btStats, s)
}
sort.Sort(sort.Reverse(btStats))
for _, s := range btStats {
fmt.Printf("size: %d, count: %d\n%s\n", s.size, s.count, s.stack)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment