Skip to content

Commit db2c23f

Browse files
committed
minor
Signed-off-by: Angelo De Caro <[email protected]>
1 parent 7febab5 commit db2c23f

File tree

1 file changed

+156
-157
lines changed
  • token/services/benchmark/cmd/memcheck

1 file changed

+156
-157
lines changed

token/services/benchmark/cmd/memcheck/main.go

Lines changed: 156 additions & 157 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ package main
99
import (
1010
"flag"
1111
"fmt"
12-
"log"
1312
"os"
1413
"sort"
1514
"strings"
@@ -68,165 +67,10 @@ func NewFuncStat(name, file string, line int) *FuncStat {
6867
}
6968
}
7069

71-
func main() {
72-
flag.Parse()
73-
if flag.NArg() < 1 {
74-
log.Fatal("Usage: memcheck <pprof_file>")
75-
}
76-
77-
filename := flag.Arg(0)
78-
f, err := os.Open(filename)
79-
if err != nil {
80-
log.Fatalf("Failed to open file: %v", err)
81-
}
82-
defer func() {
83-
_ = f.Close()
84-
}()
85-
86-
p, err := profile.Parse(f)
87-
if err != nil {
88-
log.Fatalf("Failed to parse profile: %v", err)
89-
}
90-
91-
// 1. Identify Metrics
92-
idxAllocSpace, idxAllocObj := -1, -1
93-
idxInUseSpace, idxInUseObj := -1, -1
94-
95-
for i, st := range p.SampleType {
96-
switch st.Type {
97-
case "alloc_space", "alloc_bytes":
98-
idxAllocSpace = i
99-
case "alloc_objects", "alloc_count":
100-
idxAllocObj = i
101-
case "inuse_space", "inuse_bytes":
102-
idxInUseSpace = i
103-
case "inuse_objects", "inuse_count":
104-
idxInUseObj = i
105-
}
106-
}
107-
108-
if idxAllocSpace == -1 {
109-
log.Fatal("Profile missing 'alloc_space'. Ensure this is a heap profile.")
110-
}
111-
112-
// 2. Aggregate Data
113-
stats := make(map[string]*FuncStat)
114-
lineStats := make(map[string]*LineStat)
115-
labelStats := make(map[string]*LabelStat)
116-
var totalAllocBytes, totalInUseBytes int64
117-
var topStacks []StackRecord
118-
119-
for _, s := range p.Sample {
120-
allocBytes := s.Value[idxAllocSpace]
121-
allocObj := s.Value[idxAllocObj]
122-
inUseBytes := s.Value[idxInUseSpace]
123-
inUseObj := s.Value[idxInUseObj]
124-
125-
totalAllocBytes += allocBytes
126-
totalInUseBytes += inUseBytes
127-
128-
// A. Function Analysis
129-
seen := make(map[string]bool)
130-
if len(s.Location) > 0 {
131-
leafLoc := s.Location[0]
132-
if len(leafLoc.Line) > 0 {
133-
fn := leafLoc.Line[0].Function
134-
lineNo := int(leafLoc.Line[0].Line)
135-
136-
if fn != nil {
137-
key := funcKey(fn)
138-
if _, ok := stats[key]; !ok {
139-
stats[key] = NewFuncStat(fn.Name, fn.Filename, lineNo)
140-
}
141-
stats[key].FlatAllocBytes += allocBytes
142-
stats[key].FlatAllocObj += allocObj
143-
stats[key].FlatInUseBytes += inUseBytes
144-
stats[key].FlatInUseObj += inUseObj
145-
146-
if len(s.Location) > 1 {
147-
parentLoc := s.Location[1]
148-
if len(parentLoc.Line) > 0 {
149-
pFn := parentLoc.Line[0].Function
150-
if pFn != nil {
151-
stats[key].Callers[pFn.Name] += allocBytes
152-
}
153-
}
154-
}
155-
156-
// Line Stat
157-
lineKey := fmt.Sprintf("%s:%d", fn.Filename, lineNo)
158-
if _, ok := lineStats[lineKey]; !ok {
159-
lineStats[lineKey] = &LineStat{File: fn.Filename, Line: lineNo, Function: fn.Name}
160-
}
161-
lineStats[lineKey].AllocBytes += allocBytes
162-
}
163-
}
164-
}
165-
166-
// B. Stack Trace Collection (Cumulative & Tree)
167-
var currentStack []string
168-
for _, loc := range s.Location {
169-
for _, line := range loc.Line {
170-
fn := line.Function
171-
if fn == nil {
172-
continue
173-
}
174-
currentStack = append(currentStack, fn.Name)
175-
176-
key := funcKey(fn)
177-
if seen[key] {
178-
continue
179-
}
180-
seen[key] = true
181-
182-
if _, ok := stats[key]; !ok {
183-
stats[key] = NewFuncStat(fn.Name, fn.Filename, int(line.Line))
184-
}
185-
stats[key].CumAllocBytes += allocBytes
186-
}
187-
}
188-
189-
// C. Label Analysis
190-
for key, values := range s.Label {
191-
for _, val := range values {
192-
labelID := fmt.Sprintf("%s:%s", key, val)
193-
if _, ok := labelStats[labelID]; !ok {
194-
labelStats[labelID] = &LabelStat{Name: labelID}
195-
}
196-
labelStats[labelID].AllocBytes += allocBytes
197-
labelStats[labelID].InUseBytes += inUseBytes
198-
}
199-
}
200-
201-
if allocBytes > 0 {
202-
topStacks = append(topStacks, StackRecord{Stack: currentStack, Bytes: allocBytes})
203-
}
204-
}
205-
206-
// 3. Sorting
207-
var statList []*FuncStat
208-
for _, s := range stats {
209-
statList = append(statList, s)
210-
}
211-
var labelList []*LabelStat
212-
for _, s := range labelStats {
213-
labelList = append(labelList, s)
214-
}
215-
sort.Slice(labelList, func(i, j int) bool { return labelList[i].AllocBytes > labelList[j].AllocBytes })
216-
var lineList []*LineStat
217-
for _, s := range lineStats {
218-
lineList = append(lineList, s)
219-
}
220-
sort.Slice(lineList, func(i, j int) bool { return lineList[i].AllocBytes > lineList[j].AllocBytes })
221-
222-
// 5. Generate Report
223-
printUnifiedReport(statList, labelList, lineList, topStacks, totalAllocBytes, totalInUseBytes)
224-
}
225-
22670
func printUnifiedReport(stats []*FuncStat, labels []*LabelStat, lines []*LineStat, stacks []StackRecord, totalAlloc, totalInUse int64) {
22771
w := tabwriter.NewWriter(os.Stdout, 0, 0, 2, ' ', 0)
22872

229-
writef(w, "\n================ ULTIMATE GO MEMORY ANALYZER ================\n")
73+
writef(w, "\n================ MEMORY ANALYZER ================\n")
23074
writef(w, "Total Allocated: %s | Total In-Use: %s\n\n", formatBytes(totalAlloc), formatBytes(totalInUse))
23175

23276
detectAntiPatterns(stats, w)
@@ -585,3 +429,158 @@ func writef(w *tabwriter.Writer, format string, a ...interface{}) {
585429
func writeLine(w *tabwriter.Writer, s string) {
586430
_, _ = fmt.Fprintln(w, s)
587431
}
432+
433+
func main() {
434+
flag.Parse()
435+
if flag.NArg() < 1 {
436+
log.Fatal("Usage: memcheck <pprof_file>")
437+
}
438+
439+
filename := flag.Arg(0)
440+
f, err := os.Open(filename)
441+
if err != nil {
442+
log.Fatalf("Failed to open file: %v", err)
443+
}
444+
defer func() {
445+
_ = f.Close()
446+
}()
447+
448+
p, err := profile.Parse(f)
449+
if err != nil {
450+
log.Fatalf("Failed to parse profile: %v", err)
451+
}
452+
453+
// 1. Identify Metrics
454+
idxAllocSpace, idxAllocObj := -1, -1
455+
idxInUseSpace, idxInUseObj := -1, -1
456+
457+
for i, st := range p.SampleType {
458+
switch st.Type {
459+
case "alloc_space", "alloc_bytes":
460+
idxAllocSpace = i
461+
case "alloc_objects", "alloc_count":
462+
idxAllocObj = i
463+
case "inuse_space", "inuse_bytes":
464+
idxInUseSpace = i
465+
case "inuse_objects", "inuse_count":
466+
idxInUseObj = i
467+
}
468+
}
469+
470+
if idxAllocSpace == -1 {
471+
log.Fatal("Profile missing 'alloc_space'. Ensure this is a heap profile.")
472+
}
473+
474+
// 2. Aggregate Data
475+
stats := make(map[string]*FuncStat)
476+
lineStats := make(map[string]*LineStat)
477+
labelStats := make(map[string]*LabelStat)
478+
var totalAllocBytes, totalInUseBytes int64
479+
var topStacks []StackRecord
480+
481+
for _, s := range p.Sample {
482+
allocBytes := s.Value[idxAllocSpace]
483+
allocObj := s.Value[idxAllocObj]
484+
inUseBytes := s.Value[idxInUseSpace]
485+
inUseObj := s.Value[idxInUseObj]
486+
487+
totalAllocBytes += allocBytes
488+
totalInUseBytes += inUseBytes
489+
490+
// A. Function Analysis
491+
seen := make(map[string]bool)
492+
if len(s.Location) > 0 {
493+
leafLoc := s.Location[0]
494+
if len(leafLoc.Line) > 0 {
495+
fn := leafLoc.Line[0].Function
496+
lineNo := int(leafLoc.Line[0].Line)
497+
498+
if fn != nil {
499+
key := funcKey(fn)
500+
if _, ok := stats[key]; !ok {
501+
stats[key] = NewFuncStat(fn.Name, fn.Filename, lineNo)
502+
}
503+
stats[key].FlatAllocBytes += allocBytes
504+
stats[key].FlatAllocObj += allocObj
505+
stats[key].FlatInUseBytes += inUseBytes
506+
stats[key].FlatInUseObj += inUseObj
507+
508+
if len(s.Location) > 1 {
509+
parentLoc := s.Location[1]
510+
if len(parentLoc.Line) > 0 {
511+
pFn := parentLoc.Line[0].Function
512+
if pFn != nil {
513+
stats[key].Callers[pFn.Name] += allocBytes
514+
}
515+
}
516+
}
517+
518+
// Line Stat
519+
lineKey := fmt.Sprintf("%s:%d", fn.Filename, lineNo)
520+
if _, ok := lineStats[lineKey]; !ok {
521+
lineStats[lineKey] = &LineStat{File: fn.Filename, Line: lineNo, Function: fn.Name}
522+
}
523+
lineStats[lineKey].AllocBytes += allocBytes
524+
}
525+
}
526+
}
527+
528+
// B. Stack Trace Collection (Cumulative & Tree)
529+
var currentStack []string
530+
for _, loc := range s.Location {
531+
for _, line := range loc.Line {
532+
fn := line.Function
533+
if fn == nil {
534+
continue
535+
}
536+
currentStack = append(currentStack, fn.Name)
537+
538+
key := funcKey(fn)
539+
if seen[key] {
540+
continue
541+
}
542+
seen[key] = true
543+
544+
if _, ok := stats[key]; !ok {
545+
stats[key] = NewFuncStat(fn.Name, fn.Filename, int(line.Line))
546+
}
547+
stats[key].CumAllocBytes += allocBytes
548+
}
549+
}
550+
551+
// C. Label Analysis
552+
for key, values := range s.Label {
553+
for _, val := range values {
554+
labelID := fmt.Sprintf("%s:%s", key, val)
555+
if _, ok := labelStats[labelID]; !ok {
556+
labelStats[labelID] = &LabelStat{Name: labelID}
557+
}
558+
labelStats[labelID].AllocBytes += allocBytes
559+
labelStats[labelID].InUseBytes += inUseBytes
560+
}
561+
}
562+
563+
if allocBytes > 0 {
564+
topStacks = append(topStacks, StackRecord{Stack: currentStack, Bytes: allocBytes})
565+
}
566+
}
567+
568+
// 3. Sorting
569+
var statList []*FuncStat
570+
for _, s := range stats {
571+
statList = append(statList, s)
572+
}
573+
var labelList []*LabelStat
574+
for _, s := range labelStats {
575+
labelList = append(labelList, s)
576+
}
577+
sort.Slice(labelList, func(i, j int) bool { return labelList[i].AllocBytes > labelList[j].AllocBytes })
578+
var lineList []*LineStat
579+
for _, s := range lineStats {
580+
lineList = append(lineList, s)
581+
}
582+
sort.Slice(lineList, func(i, j int) bool { return lineList[i].AllocBytes > lineList[j].AllocBytes })
583+
584+
// 5. Generate Report
585+
printUnifiedReport(statList, labelList, lineList, topStacks, totalAllocBytes, totalInUseBytes)
586+
}

0 commit comments

Comments
 (0)