runtime-info.go 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  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. "chan send": ">", // missing
  29. }
  30. // 2K works, we don't have to grow any more.
  31. if buffer == nil {
  32. buffer = make([]byte, 2048)
  33. }
  34. read := runtime.Stack(buffer, true)
  35. if read == cap(buffer) {
  36. log.Printf("Increasing buffer from (%d bytes)\n", cap(buffer))
  37. buffer = make([]byte, cap(buffer)+1024)
  38. return GoRoutinesStatus()
  39. }
  40. // fmt.Println(string(buffer[0:read]))
  41. var reader = bytes.NewReader(buffer[0:read])
  42. var scanner = bufio.NewScanner(reader)
  43. for scanner.Scan() {
  44. var text = scanner.Text()
  45. if strings.HasPrefix(text, "goroutine ") {
  46. // fmt.Println(text)
  47. // goroutine 20 [runnable]:
  48. // goroutine 1 [select, 1 minutes]:
  49. // goroutine 17 [chan receive]:
  50. // Get ID and get Status.
  51. parts := strings.SplitN(text, " ", 3)
  52. /*
  53. gid, err := strconv.Atoi(parts[1])
  54. if err != nil {
  55. continue
  56. }
  57. */
  58. status := parts[2][1 : len(parts[2])-2]
  59. if strings.Contains(status, ",") {
  60. status = strings.Split(status, ",")[0]
  61. }
  62. rstatus, ok := GStatus[status]
  63. if ok {
  64. result += rstatus
  65. } else {
  66. log.Printf("Status %s not found.\n[%s]\n", rstatus, text)
  67. }
  68. }
  69. }
  70. return result
  71. }
  72. // Return a nicely formatted string representing memory usage.
  73. func ReprMem(size uint64) string {
  74. var value float64 = float64(size)
  75. var units string = ""
  76. if value > 1024 {
  77. // In KB
  78. units = "K"
  79. value /= 1024
  80. }
  81. if value > 1024 {
  82. // In MB
  83. units = "M"
  84. value /= 1024
  85. }
  86. if value > 1024 {
  87. // Im GB
  88. units = "G"
  89. value /= 1024
  90. }
  91. var test = fmt.Sprintf("%0.2f", value)
  92. if len(test) > 4 {
  93. test = fmt.Sprintf("%0.1f", value)
  94. }
  95. if len(test) > 4 {
  96. test = fmt.Sprintf("%0.0f", value)
  97. }
  98. return test + units
  99. }
  100. // Return array of memory usage information
  101. func Memory() map[string]string {
  102. var memstats runtime.MemStats
  103. var result map[string]string = make(map[string]string, 7)
  104. runtime.ReadMemStats(&memstats)
  105. result["Heap"] = ReprMem(memstats.HeapAlloc)
  106. result["HeapInUse"] = ReprMem(memstats.HeapInuse)
  107. result["HeapSys"] = ReprMem(memstats.HeapSys)
  108. result["Sys"] = ReprMem(memstats.Sys)
  109. result["StackInUse"] = ReprMem(memstats.StackInuse)
  110. result["StackSys"] = ReprMem(memstats.StackSys)
  111. result["GCSys"] = ReprMem(memstats.GCSys)
  112. return result
  113. }