cpu.go 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. package cpu
  2. import (
  3. "fmt"
  4. "go-common/library/log"
  5. "sync/atomic"
  6. "time"
  7. )
  8. var (
  9. cores uint64
  10. maxFreq uint64
  11. quota float64
  12. usage uint64
  13. preSystem uint64
  14. preTotal uint64
  15. )
  16. func init() {
  17. cpus, err := perCPUUsage()
  18. if err != nil {
  19. panic(fmt.Errorf("stat/sys/cpu: perCPUUsage() failed!err:=%v", err))
  20. }
  21. cores = uint64(len(cpus))
  22. sets, err := cpuSets()
  23. if err != nil {
  24. panic(fmt.Errorf("stat/sys/cpu: cpuSets() failed!err:=%v", err))
  25. }
  26. quota = float64(len(sets))
  27. cq, err := cpuQuota()
  28. if err == nil {
  29. if cq != -1 {
  30. var period uint64
  31. if period, err = cpuPeriod(); err != nil {
  32. panic(fmt.Errorf("stat/sys/cpu: cpuPeriod() failed!err:=%v", err))
  33. }
  34. limit := float64(cq) / float64(period)
  35. if limit < quota {
  36. quota = limit
  37. }
  38. }
  39. }
  40. maxFreq = cpuMaxFreq()
  41. preSystem, err = systemCPUUsage()
  42. if err != nil {
  43. panic(fmt.Errorf("sys/cpu: systemCPUUsage() failed!err:=%v", err))
  44. }
  45. preTotal, err = totalCPUUsage()
  46. if err != nil {
  47. panic(fmt.Errorf("sys/cpu: totalCPUUsage() failed!err:=%v", err))
  48. }
  49. go func() {
  50. ticker := time.NewTicker(time.Millisecond * 250)
  51. defer ticker.Stop()
  52. for {
  53. <-ticker.C
  54. cpu := refreshCPU()
  55. if cpu != 0 {
  56. atomic.StoreUint64(&usage, cpu)
  57. }
  58. }
  59. }()
  60. }
  61. func refreshCPU() (u uint64) {
  62. total, err := totalCPUUsage()
  63. if err != nil {
  64. log.Warn("os/stat: get totalCPUUsage failed,error(%v)", err)
  65. return
  66. }
  67. system, err := systemCPUUsage()
  68. if err != nil {
  69. log.Warn("os/stat: get systemCPUUsage failed,error(%v)", err)
  70. return
  71. }
  72. if system != preSystem {
  73. u = uint64(float64((total-preTotal)*cores*1e3) / (float64(system-preSystem) * quota))
  74. }
  75. preSystem = system
  76. preTotal = total
  77. return u
  78. }
  79. // Stat cpu stat.
  80. type Stat struct {
  81. Usage uint64 // cpu use ratio.
  82. }
  83. // Info cpu info.
  84. type Info struct {
  85. Frequency uint64
  86. Quota float64
  87. }
  88. // ReadStat read cpu stat.
  89. func ReadStat(stat *Stat) {
  90. stat.Usage = atomic.LoadUint64(&usage)
  91. }
  92. // GetInfo get cpu info.
  93. func GetInfo() Info {
  94. return Info{
  95. Frequency: maxFreq,
  96. Quota: quota,
  97. }
  98. }