cgroup_linux.go 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. package internal
  2. import (
  3. "fmt"
  4. "os"
  5. "path"
  6. "strconv"
  7. "strings"
  8. "github.com/tal-tech/go-zero/core/iox"
  9. "github.com/tal-tech/go-zero/core/lang"
  10. )
  11. const cgroupDir = "/sys/fs/cgroup"
  12. type cgroup struct {
  13. cgroups map[string]string
  14. }
  15. func (c *cgroup) acctUsageAllCpus() (uint64, error) {
  16. data, err := iox.ReadText(path.Join(c.cgroups["cpuacct"], "cpuacct.usage"))
  17. if err != nil {
  18. return 0, err
  19. }
  20. return parseUint(string(data))
  21. }
  22. func (c *cgroup) acctUsagePerCpu() ([]uint64, error) {
  23. data, err := iox.ReadText(path.Join(c.cgroups["cpuacct"], "cpuacct.usage_percpu"))
  24. if err != nil {
  25. return nil, err
  26. }
  27. var usage []uint64
  28. for _, v := range strings.Fields(string(data)) {
  29. u, err := parseUint(v)
  30. if err != nil {
  31. return nil, err
  32. }
  33. usage = append(usage, u)
  34. }
  35. return usage, nil
  36. }
  37. func (c *cgroup) cpuQuotaUs() (int64, error) {
  38. data, err := iox.ReadText(path.Join(c.cgroups["cpu"], "cpu.cfs_quota_us"))
  39. if err != nil {
  40. return 0, err
  41. }
  42. return strconv.ParseInt(string(data), 10, 64)
  43. }
  44. func (c *cgroup) cpuPeriodUs() (uint64, error) {
  45. data, err := iox.ReadText(path.Join(c.cgroups["cpu"], "cpu.cfs_period_us"))
  46. if err != nil {
  47. return 0, err
  48. }
  49. return parseUint(string(data))
  50. }
  51. func (c *cgroup) cpus() ([]uint64, error) {
  52. data, err := iox.ReadText(path.Join(c.cgroups["cpuset"], "cpuset.cpus"))
  53. if err != nil {
  54. return nil, err
  55. }
  56. return parseUints(string(data))
  57. }
  58. func currentCgroup() (*cgroup, error) {
  59. cgroupFile := fmt.Sprintf("/proc/%d/cgroup", os.Getpid())
  60. lines, err := iox.ReadTextLines(cgroupFile, iox.WithoutBlank())
  61. if err != nil {
  62. return nil, err
  63. }
  64. cgroups := make(map[string]string)
  65. for _, line := range lines {
  66. cols := strings.Split(line, ":")
  67. if len(cols) != 3 {
  68. return nil, fmt.Errorf("invalid cgroup line: %s", line)
  69. }
  70. subsys := cols[1]
  71. // only read cpu staff
  72. if !strings.HasPrefix(subsys, "cpu") {
  73. continue
  74. }
  75. if strings.Contains(subsys, ",") {
  76. for _, k := range strings.Split(subsys, ",") {
  77. cgroups[k] = path.Join(cgroupDir, k)
  78. }
  79. } else {
  80. cgroups[subsys] = path.Join(cgroupDir, subsys)
  81. }
  82. }
  83. return &cgroup{
  84. cgroups: cgroups,
  85. }, nil
  86. }
  87. func parseUint(s string) (uint64, error) {
  88. v, err := strconv.ParseInt(s, 10, 64)
  89. if err != nil {
  90. if err.(*strconv.NumError).Err == strconv.ErrRange {
  91. return 0, nil
  92. } else {
  93. return 0, fmt.Errorf("cgroup: bad int format: %s", s)
  94. }
  95. } else {
  96. if v < 0 {
  97. return 0, nil
  98. } else {
  99. return uint64(v), nil
  100. }
  101. }
  102. }
  103. func parseUints(val string) ([]uint64, error) {
  104. if val == "" {
  105. return nil, nil
  106. }
  107. ints := make(map[uint64]lang.PlaceholderType)
  108. cols := strings.Split(val, ",")
  109. for _, r := range cols {
  110. if strings.Contains(r, "-") {
  111. fields := strings.SplitN(r, "-", 2)
  112. min, err := parseUint(fields[0])
  113. if err != nil {
  114. return nil, fmt.Errorf("cgroup: bad int list format: %s", val)
  115. }
  116. max, err := parseUint(fields[1])
  117. if err != nil {
  118. return nil, fmt.Errorf("cgroup: bad int list format: %s", val)
  119. }
  120. if max < min {
  121. return nil, fmt.Errorf("cgroup: bad int list format: %s", val)
  122. }
  123. for i := min; i <= max; i++ {
  124. ints[i] = lang.Placeholder
  125. }
  126. } else {
  127. v, err := parseUint(r)
  128. if err != nil {
  129. return nil, err
  130. }
  131. ints[v] = lang.Placeholder
  132. }
  133. }
  134. var sets []uint64
  135. for k := range ints {
  136. sets = append(sets, k)
  137. }
  138. return sets, nil
  139. }