cgroup.go 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. // +build linux
  2. package cpu
  3. import (
  4. "bufio"
  5. "fmt"
  6. "io"
  7. "os"
  8. "path"
  9. "strconv"
  10. "strings"
  11. )
  12. const cgroupRootDir = "/sys/fs/cgroup"
  13. // cgroup Linux cgroup
  14. type cgroup struct {
  15. cgroupSet map[string]string
  16. }
  17. // CPUCFSQuotaUs cpu.cfs_quota_us
  18. func (c *cgroup) CPUCFSQuotaUs() (int64, error) {
  19. data, err := readFile(path.Join(c.cgroupSet["cpu"], "cpu.cfs_quota_us"))
  20. if err != nil {
  21. return 0, err
  22. }
  23. return strconv.ParseInt(data, 10, 64)
  24. }
  25. // CPUCFSPeriodUs cpu.cfs_period_us
  26. func (c *cgroup) CPUCFSPeriodUs() (uint64, error) {
  27. data, err := readFile(path.Join(c.cgroupSet["cpu"], "cpu.cfs_period_us"))
  28. if err != nil {
  29. return 0, err
  30. }
  31. return parseUint(data)
  32. }
  33. // CPUAcctUsage cpuacct.usage
  34. func (c *cgroup) CPUAcctUsage() (uint64, error) {
  35. data, err := readFile(path.Join(c.cgroupSet["cpuacct"], "cpuacct.usage"))
  36. if err != nil {
  37. return 0, err
  38. }
  39. return parseUint(data)
  40. }
  41. // CPUAcctUsagePerCPU cpuacct.usage_percpu
  42. func (c *cgroup) CPUAcctUsagePerCPU() ([]uint64, error) {
  43. data, err := readFile(path.Join(c.cgroupSet["cpuacct"], "cpuacct.usage_percpu"))
  44. if err != nil {
  45. return nil, err
  46. }
  47. var usage []uint64
  48. for _, v := range strings.Fields(string(data)) {
  49. var u uint64
  50. if u, err = parseUint(v); err != nil {
  51. return nil, err
  52. }
  53. usage = append(usage, u)
  54. }
  55. return usage, nil
  56. }
  57. // CPUSetCPUs cpuset.cpus
  58. func (c *cgroup) CPUSetCPUs() ([]uint64, error) {
  59. data, err := readFile(path.Join(c.cgroupSet["cpuset"], "cpuset.cpus"))
  60. if err != nil {
  61. return nil, err
  62. }
  63. cpus, err := ParseUintList(data)
  64. if err != nil {
  65. return nil, err
  66. }
  67. var sets []uint64
  68. for k := range cpus {
  69. sets = append(sets, uint64(k))
  70. }
  71. return sets, nil
  72. }
  73. // CurrentcGroup get current process cgroup
  74. func currentcGroup() (*cgroup, error) {
  75. pid := os.Getpid()
  76. cgroupFile := fmt.Sprintf("/proc/%d/cgroup", pid)
  77. cgroupSet := make(map[string]string)
  78. fp, err := os.Open(cgroupFile)
  79. if err != nil {
  80. return nil, err
  81. }
  82. defer fp.Close()
  83. buf := bufio.NewReader(fp)
  84. for {
  85. line, err := buf.ReadString('\n')
  86. if err != nil {
  87. if err == io.EOF {
  88. break
  89. }
  90. return nil, err
  91. }
  92. col := strings.Split(strings.TrimSpace(line), ":")
  93. if len(col) != 3 {
  94. return nil, fmt.Errorf("invalid cgroup format %s", line)
  95. }
  96. dir := col[2]
  97. // When dir is not equal to /, it must be in docker
  98. if dir != "/" {
  99. cgroupSet[col[1]] = path.Join(cgroupRootDir, col[1])
  100. if strings.Contains(col[1], ",") {
  101. for _, k := range strings.Split(col[1], ",") {
  102. cgroupSet[k] = path.Join(cgroupRootDir, k)
  103. }
  104. }
  105. } else {
  106. cgroupSet[col[1]] = path.Join(cgroupRootDir, col[1], col[2])
  107. if strings.Contains(col[1], ",") {
  108. for _, k := range strings.Split(col[1], ",") {
  109. cgroupSet[k] = path.Join(cgroupRootDir, k, col[2])
  110. }
  111. }
  112. }
  113. }
  114. return &cgroup{cgroupSet: cgroupSet}, nil
  115. }