mirror of
https://github.com/jimeh/rbheap.git
synced 2026-02-19 04:46:40 +00:00
Initial work to get full output format working
This commit is contained in:
20
entry.go
Normal file
20
entry.go
Normal file
@@ -0,0 +1,20 @@
|
||||
package main
|
||||
|
||||
func NewEntry(inputJSON []byte) (*Entry, error) {
|
||||
obj, err := NewObject(inputJSON)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &Entry{
|
||||
Object: obj,
|
||||
Index: obj.Index(),
|
||||
}, err
|
||||
}
|
||||
|
||||
// Entry is a parsed heap item object
|
||||
type Entry struct {
|
||||
Object *Object
|
||||
Offset int64
|
||||
Index string
|
||||
}
|
||||
71
heap_dump.go
71
heap_dump.go
@@ -1,9 +1,11 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"bufio"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"sort"
|
||||
)
|
||||
|
||||
func NewHeapDump(file string) (*HeapDump, error) {
|
||||
@@ -16,7 +18,7 @@ func NewHeapDump(file string) (*HeapDump, error) {
|
||||
type HeapDump struct {
|
||||
File string
|
||||
Index []string
|
||||
Entries map[string]*HeapEntry
|
||||
Entries map[string]*Entry
|
||||
}
|
||||
|
||||
// Process processes the heap dump
|
||||
@@ -28,20 +30,71 @@ func (s *HeapDump) Process() error {
|
||||
return err
|
||||
}
|
||||
|
||||
s.Entries = map[string]*HeapEntry{}
|
||||
s.Entries = map[string]*Entry{}
|
||||
|
||||
d := json.NewDecoder(file)
|
||||
reader := bufio.NewReader(file)
|
||||
var offset int64 = -1
|
||||
for {
|
||||
var e HeapEntry
|
||||
if err := d.Decode(&e); err == io.EOF {
|
||||
offset++
|
||||
line, err := reader.ReadBytes(byte('\n'))
|
||||
if err == io.EOF {
|
||||
break
|
||||
} else if err != nil {
|
||||
return err
|
||||
}
|
||||
index := e.Address + ":" + e.Type
|
||||
s.Entries[index] = &e
|
||||
s.Index = append(s.Index, index)
|
||||
|
||||
entry, err := NewEntry(line)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
entry.Offset = offset
|
||||
s.Entries[entry.Index] = entry
|
||||
s.Index = append(s.Index, entry.Index)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *HeapDump) PrintMatchingJSON(indexes *[]string) error {
|
||||
file, err := os.Open(s.File)
|
||||
defer file.Close()
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
reader := bufio.NewReader(file)
|
||||
offsets := s.matchingOffsets(indexes)
|
||||
|
||||
var current int64 = 0
|
||||
var offset int64 = -1
|
||||
|
||||
for {
|
||||
offset++
|
||||
line, err := reader.ReadBytes(byte('\n'))
|
||||
if err == io.EOF {
|
||||
break
|
||||
} else if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if offset == offsets[current] {
|
||||
current++
|
||||
fmt.Print(string(line))
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *HeapDump) matchingOffsets(indexes *[]string) []int64 {
|
||||
var offsets []int64
|
||||
|
||||
for _, index := range *indexes {
|
||||
offsets = append(offsets, s.Entries[index].Offset)
|
||||
}
|
||||
|
||||
sort.Slice(offsets, func(i, j int) bool { return offsets[i] < offsets[j] })
|
||||
return offsets
|
||||
}
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
package main
|
||||
|
||||
//go:generate easyjson -all heap_entry.go
|
||||
|
||||
// HeapEntry is a parsed heap item object
|
||||
type HeapEntry struct {
|
||||
Address string `json:"address"`
|
||||
Type string `json:"type"`
|
||||
}
|
||||
22
main.go
22
main.go
@@ -49,14 +49,6 @@ func versionString() string {
|
||||
return buffer.String()
|
||||
}
|
||||
|
||||
func printHexDiff(leaked *[]string, dump *HeapDump) {
|
||||
for _, index := range *leaked {
|
||||
if item, ok := dump.Entries[index]; ok {
|
||||
fmt.Printf("%s\n", item.Address)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func logMsg(msg string) {
|
||||
if !*silentFlag {
|
||||
fmt.Println(msg)
|
||||
@@ -70,6 +62,14 @@ func loadDump(filePath string) (*HeapDump, error) {
|
||||
return dump, err
|
||||
}
|
||||
|
||||
func printHexDiff(leaked *[]string, dump *HeapDump) {
|
||||
for _, index := range *leaked {
|
||||
if entry, ok := dump.Entries[index]; ok {
|
||||
fmt.Println(entry.Object.Address)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
kingpin.Version(versionString())
|
||||
kingpin.Parse()
|
||||
@@ -93,7 +93,7 @@ func main() {
|
||||
|
||||
if *formatFlag == "hex" {
|
||||
printHexDiff(leaked, dump2)
|
||||
} // else if *formatFlag == 'full' {
|
||||
// printFullDiff(leaked, dump2)
|
||||
// }
|
||||
} else if *formatFlag == "full" {
|
||||
dump2.PrintMatchingJSON(leaked)
|
||||
}
|
||||
}
|
||||
|
||||
21
object.go
Normal file
21
object.go
Normal file
@@ -0,0 +1,21 @@
|
||||
package main
|
||||
|
||||
import "encoding/json"
|
||||
|
||||
//go:generate easyjson -all object.go
|
||||
|
||||
func NewObject(inputJSON []byte) (*Object, error) {
|
||||
var obj Object
|
||||
err := json.Unmarshal(inputJSON, &obj)
|
||||
|
||||
return &obj, err
|
||||
}
|
||||
|
||||
type Object struct {
|
||||
Address string `json:"address"`
|
||||
Type string `json:"type"`
|
||||
}
|
||||
|
||||
func (s *Object) Index() string {
|
||||
return s.Address + ":" + s.Type
|
||||
}
|
||||
@@ -17,7 +17,7 @@ var (
|
||||
_ easyjson.Marshaler
|
||||
)
|
||||
|
||||
func easyjson48125c2bDecodeGithubComJimehRbheapleak(in *jlexer.Lexer, out *HeapEntry) {
|
||||
func easyjsonE44bcf2dDecodeGithubComJimehRbheapleak(in *jlexer.Lexer, out *Object) {
|
||||
isTopLevel := in.IsStart()
|
||||
if in.IsNull() {
|
||||
if isTopLevel {
|
||||
@@ -50,7 +50,7 @@ func easyjson48125c2bDecodeGithubComJimehRbheapleak(in *jlexer.Lexer, out *HeapE
|
||||
in.Consumed()
|
||||
}
|
||||
}
|
||||
func easyjson48125c2bEncodeGithubComJimehRbheapleak(out *jwriter.Writer, in HeapEntry) {
|
||||
func easyjsonE44bcf2dEncodeGithubComJimehRbheapleak(out *jwriter.Writer, in Object) {
|
||||
out.RawByte('{')
|
||||
first := true
|
||||
_ = first
|
||||
@@ -78,25 +78,25 @@ func easyjson48125c2bEncodeGithubComJimehRbheapleak(out *jwriter.Writer, in Heap
|
||||
}
|
||||
|
||||
// MarshalJSON supports json.Marshaler interface
|
||||
func (v HeapEntry) MarshalJSON() ([]byte, error) {
|
||||
func (v Object) MarshalJSON() ([]byte, error) {
|
||||
w := jwriter.Writer{}
|
||||
easyjson48125c2bEncodeGithubComJimehRbheapleak(&w, v)
|
||||
easyjsonE44bcf2dEncodeGithubComJimehRbheapleak(&w, v)
|
||||
return w.Buffer.BuildBytes(), w.Error
|
||||
}
|
||||
|
||||
// MarshalEasyJSON supports easyjson.Marshaler interface
|
||||
func (v HeapEntry) MarshalEasyJSON(w *jwriter.Writer) {
|
||||
easyjson48125c2bEncodeGithubComJimehRbheapleak(w, v)
|
||||
func (v Object) MarshalEasyJSON(w *jwriter.Writer) {
|
||||
easyjsonE44bcf2dEncodeGithubComJimehRbheapleak(w, v)
|
||||
}
|
||||
|
||||
// UnmarshalJSON supports json.Unmarshaler interface
|
||||
func (v *HeapEntry) UnmarshalJSON(data []byte) error {
|
||||
func (v *Object) UnmarshalJSON(data []byte) error {
|
||||
r := jlexer.Lexer{Data: data}
|
||||
easyjson48125c2bDecodeGithubComJimehRbheapleak(&r, v)
|
||||
easyjsonE44bcf2dDecodeGithubComJimehRbheapleak(&r, v)
|
||||
return r.Error()
|
||||
}
|
||||
|
||||
// UnmarshalEasyJSON supports easyjson.Unmarshaler interface
|
||||
func (v *HeapEntry) UnmarshalEasyJSON(l *jlexer.Lexer) {
|
||||
easyjson48125c2bDecodeGithubComJimehRbheapleak(l, v)
|
||||
func (v *Object) UnmarshalEasyJSON(l *jlexer.Lexer) {
|
||||
easyjsonE44bcf2dDecodeGithubComJimehRbheapleak(l, v)
|
||||
}
|
||||
Reference in New Issue
Block a user