runtime-info.go 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. package main
  2. import (
  3. "bufio"
  4. "bytes"
  5. "fmt"
  6. "log"
  7. "runtime"
  8. "strings"
  9. )
  10. // reused by GoRuntinesStatus()
  11. var buffer []byte
  12. // Get Go Routines and map the Status. See GStatus.
  13. func GoRoutinesStatus() string {
  14. var result string
  15. // Map status to letter.
  16. var GStatus = map[string]string{
  17. "idle": "I",
  18. "runnable": "r",
  19. "running": "R",
  20. "syscall": "s",
  21. "waiting": "W",
  22. "dead": "D",
  23. "copystack": "C",
  24. "preempted": "P",
  25. "sleep": "S",
  26. "select": "s", // missing
  27. "chan receive": "<", // missing
  28. }
  29. if buffer == nil {
  30. buffer = make([]byte, 1024) // 2048)
  31. }
  32. read := runtime.Stack(buffer, true)
  33. if read == cap(buffer) {
  34. log.Printf("Increasing buffer from (%d bytes)\n", cap(buffer))
  35. buffer = make([]byte, cap(buffer)+1024)
  36. return GoRoutinesStatus()
  37. }
  38. // fmt.Println(string(buffer[0:read]))
  39. var reader = bytes.NewReader(buffer[0:read])
  40. var scanner = bufio.NewScanner(reader)
  41. for scanner.Scan() {
  42. var text = scanner.Text()
  43. if strings.HasPrefix(text, "goroutine ") {
  44. // fmt.Println(text)
  45. // goroutine 20 [runnable]:
  46. // goroutine 1 [select, 1 minutes]:
  47. // goroutine 17 [chan receive]:
  48. // Get ID and get Status.
  49. parts := strings.SplitN(text, " ", 3)
  50. /*
  51. gid, err := strconv.Atoi(parts[1])
  52. if err != nil {
  53. continue
  54. }
  55. */
  56. status := parts[2][1 : len(parts[2])-2]
  57. if strings.Contains(status, ",") {
  58. status = strings.Split(status, ",")[0]
  59. }
  60. rstatus, ok := GStatus[status]
  61. if ok {
  62. result += rstatus
  63. } else {
  64. log.Printf("Status %s not found.\n[%s]\n", rstatus, text)
  65. }
  66. }
  67. }
  68. return result
  69. }
  70. // Return a nicely formatted string representing memory usage.
  71. func ReprMem(size uint64) string {
  72. var value float64 = float64(size)
  73. var units string = ""
  74. if value > 1024 {
  75. // In KB
  76. units = "K"
  77. value /= 1024
  78. }
  79. if value > 1024 {
  80. // In MB
  81. units = "M"
  82. value /= 1024
  83. }
  84. if value > 1024 {
  85. // Im GB
  86. units = "G"
  87. value /= 1024
  88. }
  89. var test = fmt.Sprintf("%0.2f", value)
  90. if len(test) > 4 {
  91. test = fmt.Sprintf("%0.1f", value)
  92. }
  93. if len(test) > 4 {
  94. test = fmt.Sprintf("%0.0f", value)
  95. }
  96. return test + units
  97. }
  98. // Return array of memory usage information
  99. func Memory() map[string]string {
  100. var memstats runtime.MemStats
  101. var result map[string]string = make(map[string]string, 7)
  102. runtime.ReadMemStats(&memstats)
  103. result["Heap"] = ReprMem(memstats.HeapAlloc)
  104. result["HeapInUse"] = ReprMem(memstats.HeapInuse)
  105. result["HeapSys"] = ReprMem(memstats.HeapSys)
  106. result["Sys"] = ReprMem(memstats.Sys)
  107. result["StackInUse"] = ReprMem(memstats.StackInuse)
  108. result["StackSys"] = ReprMem(memstats.StackSys)
  109. result["GCSys"] = ReprMem(memstats.GCSys)
  110. return result
  111. }