diff options
| author | Jeff Carr <[email protected]> | 2024-01-04 23:28:55 -0600 |
|---|---|---|
| committer | Jeff Carr <[email protected]> | 2024-01-04 23:28:55 -0600 |
| commit | ff32316084e11911462be420dd8310473b3d26fd (patch) | |
| tree | f95e62befdccb40ed4f1b397f71a0d24ca427c3f /golang.go | |
| parent | 1f0e212002c2c5b34ea23d91e504ed59d31cab22 (diff) | |
ah, a much cleaner start to a debugger
Finally there is some sense this debugger can
finally be useful. It can be developed and worked on in
isolation from the 'gui' package therefore it can call
more sophisticated widget collections. 'gadgets'
all moved to gadgets.BasicWindow()
thank goodness all this code is isolated finally
can finally rename the files
first gadgets.BasicWindow()
Signed-off-by: Jeff Carr <[email protected]>
Diffstat (limited to 'golang.go')
| -rw-r--r-- | golang.go | 176 |
1 files changed, 176 insertions, 0 deletions
diff --git a/golang.go b/golang.go new file mode 100644 index 0000000..a037ca2 --- /dev/null +++ b/golang.go @@ -0,0 +1,176 @@ +package debugger + +import ( + "fmt" + "bytes" + // "os" + "runtime" + "runtime/debug" + "runtime/pprof" + + "go.wit.com/log" + "go.wit.com/gui/gui" + "go.wit.com/gui/gadgets" +) + +func DebugGolangWindow(p *gui.Node) *gadgets.BasicWindow { + var w *gadgets.BasicWindow + var g, og, outputTextbox *gui.Node + + w = gadgets.NewBasicWindow(p, "GO") + g = w.Box().NewGroup("Language Internals").Pad() + + g.NewButton("ReadModuleInfo()", func () { + tmp, _ := debug.ReadBuildInfo() + outputTextbox.SetText(tmp.String()) + }) + g.NewButton("runtime.NumGoroutine()", func () { + buf := new(bytes.Buffer) + pprof.Lookup("goroutine").WriteTo(buf, 1) + outputTextbox.SetText(buf.String()) + + outputTextbox.AppendText(fmt.Sprintln("runtime.NumGoroutine() = ", runtime.NumGoroutine())) + }) + g.NewButton("pprof.Lookup(heap)", func () { + buf := new(bytes.Buffer) + pprof.Lookup("heap").WriteTo(buf, 1) + outputTextbox.SetText(buf.String()) + }) + g.NewButton("debug.PrintStack(current)", func () { + outputTextbox.SetText(string(debug.Stack())) + }) + g.NewButton("pprof.Lookup(goroutine)", func () { + buf := new(bytes.Buffer) + pprof.Lookup("goroutine").WriteTo(buf, 1) + outputTextbox.SetText(buf.String()) + }) + g.NewButton("pprof.Lookup(block)", func () { + buf := new(bytes.Buffer) + pprof.Lookup("block").WriteTo(buf, 1) + outputTextbox.SetText(buf.String()) + }) + g.NewButton("pprof.Lookup threadcreate", func () { + buf := new(bytes.Buffer) + pprof.Lookup("threadcreate").WriteTo(buf, 1) + outputTextbox.SetText(buf.String()) + }) + + g.NewButton("runtime.ReadMemStats()", func () { + outputTextbox.SetText(runtimeReadMemStats()) + }) + + g.NewButton("debug.FreeOSMemory()", func () { + var out string = "Before debug.FreeOSMemory():\n\n" + out += runtimeReadMemStats() + debug.FreeOSMemory() + out += "\n\nAfter debug.FreeOSMemory():\n\n" + out += runtimeReadMemStats() + outputTextbox.SetText(out) + }) + + g.NewButton("debug.ReadGCStats()", func () { + var tmp debug.GCStats + var out string + debug.ReadGCStats(&tmp) + log.Log(true, tmp) + out += fmt.Sprintln("LastGC:", tmp.LastGC, "// time.Time time of last collection") + out += fmt.Sprintln("NumGC:", tmp.NumGC, "// number of garbage collections") + out += fmt.Sprintln("PauseTotal:", tmp.PauseTotal, "// total pause for all collections") + out += fmt.Sprintln("Pause:", tmp.Pause, "// []time.Duration pause history, most recent first") + out += fmt.Sprintln("PauseEnd:", tmp.Pause, "// []time.Time pause history, most recent first") + out += fmt.Sprintln("PauseQuantiles:", tmp.PauseQuantiles, "// []time.Duration") + outputTextbox.SetText(out) + }) + + g.NewButton("debug.SetTraceback('all')", func () { + debug.SetTraceback("all") + }) + + g.NewButton("panic()", func () { + panic("test") + }) + + g = w.Box().NewGroup("TODO: finish these").Pad() + + // g.NewLabel("TODO:") + + g.NewButton("runtime.Stack(true)", func () { + // TODO: https://stackoverflow.com/questions/61127053/how-to-list-all-the-running-goroutines-in-a-go-program + // func Stack(buf []byte, all bool) int + }) + + g.NewButton("debug.SetMemoryLimit(int)", func () { + // TODO: + //debug.SetMemoryLimit(1024 * 1024 * 100) + }) + + g.NewButton("debug.SetMaxStack(int bytes)", func () { + // default is apparently 1GB + }) + + g.NewButton("debug.SetMaxThreads(int)", func () { + // default is apparently 10,000 + }) + + g.NewButton("debug.SetTraceback('all')", func () { + debug.SetTraceback("all") + }) + + // deprecated (probably) by String() implementation within golang + g.NewButton("dumpModuleInfo() (deprecate)", func () { + outputTextbox.SetText(dumpModuleInfo()) + }) + + og = w.Box().NewGroup("output").Pad() + outputTextbox = og.NewTextbox("outputBox") + outputTextbox.Custom = func () { + log.Log(true, "custom TextBox() for golang output a =", outputTextbox.S) + } + + return w +} + +func runtimeReadMemStats() string { + var s runtime.MemStats + var out string + runtime.ReadMemStats(&s) + out += fmt.Sprintln("alloc:", s.Alloc, "bytes") + out += fmt.Sprintln("total-alloc:", s.TotalAlloc, "bytes") + out += fmt.Sprintln("sys:", s.Sys, "bytes") + out += fmt.Sprintln("lookups:", s.Lookups) + out += fmt.Sprintln("mallocs:", s.Mallocs) + out += fmt.Sprintln("frees:", s.Frees) + out += fmt.Sprintln("heap-alloc:", s.HeapAlloc, "bytes") + out += fmt.Sprintln("heap-sys:", s.HeapSys, "bytes") + out += fmt.Sprintln("heap-idle:", s.HeapIdle,"bytes") + out += fmt.Sprintln("heap-in-use:", s.HeapInuse, "bytes") + out += fmt.Sprintln("heap-released:", s.HeapReleased, "bytes") + out += fmt.Sprintln("heap-objects:", s.HeapObjects) + out += fmt.Sprintln("stack-in-use:", s.StackInuse, "bytes") + out += fmt.Sprintln("stack-sys", s.StackSys, "bytes") + out += fmt.Sprintln("next-gc: when heap-alloc >=", s.NextGC, "bytes") + out += fmt.Sprintln("last-gc:", s.LastGC, "ns") + out += fmt.Sprintln("gc-pause:", s.PauseTotalNs, "ns") + out += fmt.Sprintln("num-gc:", s.NumGC) + out += fmt.Sprintln("enable-gc:", s.EnableGC) + out += fmt.Sprintln("debug-gc:", s.DebugGC) + return out +} + +func dumpModuleInfo() string { + var out string + tmp, _ := debug.ReadBuildInfo() + if tmp == nil { + out += fmt.Sprintln("This wasn't compiled with go module support") + return "" + } + out += fmt.Sprintln("mod.Path = ", tmp.Path) + out += fmt.Sprintln("mod.Main.Path = ", tmp.Main.Path) + out += fmt.Sprintln("mod.Main.Version = ", tmp.Main.Version) + out += fmt.Sprintln("mod.Main.Sum = ", tmp.Main.Sum) + for _, value := range tmp.Deps { + out += fmt.Sprintln("\tmod.Path = ", value.Path) + out += fmt.Sprintln("\tmod.Version = ", value.Version) + } + return out +} |
