Created
April 5, 2018 20:52
-
-
Save siddontang/8d5e4c8029e5b1df481546063842be91 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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