Skip to content

Commit c85acdc

Browse files
committed
proxy: getrusage is deprecated, using /proc/self/stat instead
1 parent 42d4014 commit c85acdc

File tree

6 files changed

+198
-68
lines changed

6 files changed

+198
-68
lines changed

cmd/proxy/main.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,7 @@ func AutoGOMAXPROCS(min, max int) {
196196
var less, more int
197197
var usage [10]float64
198198
for i := 0; i < len(usage) && more == 0; i++ {
199-
u, err := utils.CPUUsage(time.Second)
199+
u, _, err := utils.CPUUsage(time.Second)
200200
if err != nil {
201201
log.WarnErrorf(err, "get cpu usage failed")
202202
time.Sleep(time.Second * 30)

pkg/proxy/proxy.go

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -476,8 +476,10 @@ type Stats struct {
476476
} `json:"sessions"`
477477

478478
Rusage struct {
479-
Mem int64 `json:"mem"`
480-
CPU float64 `json:"cpu"`
479+
Now string `json:"now"`
480+
CPU float64 `json:"cpu"`
481+
Mem int64 `json:"mem"`
482+
Raw *utils.Usage `json:"raw,omitempty"`
481483
} `json:"rusage"`
482484

483485
Backend struct {
@@ -566,8 +568,12 @@ func (s *Proxy) Stats(flags StatsFlags) *Stats {
566568
stats.Sessions.Total = SessionsTotal()
567569
stats.Sessions.Alive = SessionsAlive()
568570

569-
stats.Rusage.Mem = GetSysMemTotal()
570-
stats.Rusage.CPU = GetSysCPUUsage()
571+
if u := GetSysUsage(); u != nil {
572+
stats.Rusage.Now = u.Now.String()
573+
stats.Rusage.CPU = u.CPU
574+
stats.Rusage.Mem = u.MemTotal()
575+
stats.Rusage.Raw = u.Usage
576+
}
571577

572578
stats.Backend.PrimaryOnly = s.Config().BackendPrimaryOnly
573579

pkg/proxy/stats.go

Lines changed: 25 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"math"
88
"sort"
99
"sync"
10+
"sync/atomic"
1011
"time"
1112

1213
"github.com/CodisLabs/codis/pkg/utils"
@@ -184,40 +185,38 @@ func SessionsAlive() int64 {
184185
return sessions.alive.Get()
185186
}
186187

187-
var sysUsage struct {
188-
mem int64
189-
cpu float64
188+
type SysUsage struct {
189+
Now time.Time
190+
CPU float64
191+
*utils.Usage
190192
}
191193

194+
var lastSysUsage atomic.Value
195+
192196
func init() {
193-
updateSysUsage := func() error {
194-
mem, err := utils.MemTotal()
195-
if err != nil {
196-
return err
197-
}
198-
cpu, err := utils.CPUUsage(time.Second)
199-
if err != nil {
200-
return err
201-
}
202-
sysUsage.mem = mem
203-
sysUsage.cpu = cpu
204-
return nil
205-
}
206197
go func() {
207198
for {
208-
if err := updateSysUsage(); err != nil {
209-
sysUsage.mem = 0
210-
sysUsage.cpu = 0
211-
time.Sleep(time.Second)
199+
cpu, usage, err := utils.CPUUsage(time.Second)
200+
if err != nil {
201+
lastSysUsage.Store(&SysUsage{
202+
Now: time.Now(),
203+
})
204+
} else {
205+
lastSysUsage.Store(&SysUsage{
206+
Now: time.Now(),
207+
CPU: cpu, Usage: usage,
208+
})
209+
}
210+
if err != nil {
211+
time.Sleep(time.Second * 5)
212212
}
213213
}
214214
}()
215215
}
216216

217-
func GetSysMemTotal() int64 {
218-
return sysUsage.mem
219-
}
220-
221-
func GetSysCPUUsage() float64 {
222-
return sysUsage.cpu
217+
func GetSysUsage() *SysUsage {
218+
if p := lastSysUsage.Load(); p != nil {
219+
return p.(*SysUsage)
220+
}
221+
return nil
223222
}

pkg/utils/usage.go

Lines changed: 8 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -3,48 +3,19 @@
33

44
package utils
55

6-
import (
7-
"syscall"
8-
"time"
6+
import "time"
97

10-
"github.com/CodisLabs/codis/pkg/utils/errors"
11-
)
12-
13-
func SysUsage() (*syscall.Rusage, error) {
14-
var usage syscall.Rusage
15-
if err := syscall.Getrusage(syscall.RUSAGE_SELF, &usage); err != nil {
16-
return nil, errors.Trace(err)
17-
}
18-
return &usage, nil
19-
}
20-
21-
func MemTotal() (int64, error) {
22-
u, err := SysUsage()
23-
if err != nil {
24-
return 0, errors.Trace(err)
25-
}
26-
return (u.Idrss + u.Isrss) * 1024, nil
27-
}
28-
29-
func CPUTotal() (time.Duration, error) {
30-
u, err := SysUsage()
31-
if err != nil {
32-
return 0, errors.Trace(err)
33-
}
34-
return time.Duration(u.Utime.Nano() + u.Stime.Nano()), nil
35-
}
36-
37-
func CPUUsage(d time.Duration) (float64, error) {
8+
func CPUUsage(d time.Duration) (float64, *Usage, error) {
389
var now = time.Now()
39-
b, err := CPUTotal()
10+
b, err := GetUsage()
4011
if err != nil {
41-
return 0, err
12+
return 0, nil, err
4213
}
4314
time.Sleep(d)
44-
e, err := CPUTotal()
15+
e, err := GetUsage()
4516
if err != nil {
46-
return 0, err
17+
return 0, nil, err
4718
}
48-
usage := e - b
49-
return float64(usage) / float64(time.Since(now)), nil
19+
usage := e.CPUTotal() - b.CPUTotal()
20+
return float64(usage) / float64(time.Since(now)), e, nil
5021
}

pkg/utils/usage_linux.go

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
// Copyright 2016 CodisLabs. All Rights Reserved.
2+
// Licensed under the MIT (MIT-LICENSE.txt) license.
3+
4+
// +build linux
5+
6+
package utils
7+
8+
import (
9+
"bufio"
10+
"fmt"
11+
"os"
12+
"syscall"
13+
"time"
14+
15+
"github.com/CodisLabs/codis/pkg/utils/errors"
16+
)
17+
18+
/*
19+
#include <unistd.h>
20+
*/
21+
import "C"
22+
23+
type Usage struct {
24+
Utime time.Duration `json:"utime"`
25+
Stime time.Duration `json:"stime"`
26+
Cutime time.Duration `json:"cutime"`
27+
Cstime time.Duration `json:"cstime"`
28+
29+
NumThreads int `json:"num_threads"`
30+
31+
VmSize int64 `json:"vm_size"`
32+
VmRss int64 `json:"vm_rss"`
33+
}
34+
35+
func (u *Usage) MemTotal() int64 {
36+
return u.VmRss
37+
}
38+
39+
func (u *Usage) CPUTotal() time.Duration {
40+
return time.Duration(u.Utime + u.Stime + u.Cutime + u.Cstime)
41+
}
42+
43+
func GetUsage() (*Usage, error) {
44+
f, err := os.Open("/proc/self/stat")
45+
if err != nil {
46+
return nil, errors.Trace(err)
47+
}
48+
defer f.Close()
49+
50+
var ignore struct {
51+
s string
52+
d int64
53+
}
54+
55+
r := bufio.NewReader(f)
56+
u := &Usage{}
57+
if _, err := fmt.Fscanf(r, "%d %s %s %d %d %d",
58+
&ignore.d, &ignore.s, &ignore.s, &ignore.d, &ignore.d, &ignore.d); err != nil {
59+
return nil, errors.Trace(err)
60+
}
61+
if _, err := fmt.Fscanf(r, "%d %d %d",
62+
&ignore.d, &ignore.d, &ignore.d); err != nil {
63+
return nil, errors.Trace(err)
64+
}
65+
if _, err := fmt.Fscanf(r, "%d %d %d %d",
66+
&ignore.d, &ignore.d, &ignore.d, &ignore.d); err != nil {
67+
return nil, errors.Trace(err)
68+
}
69+
70+
var ticks struct {
71+
u int64
72+
s int64
73+
}
74+
unit := time.Second / time.Duration(C.sysconf(C._SC_CLK_TCK))
75+
76+
if _, err := fmt.Fscanf(r, "%d %d",
77+
&ticks.u, &ticks.s); err != nil {
78+
return nil, errors.Trace(err)
79+
}
80+
u.Utime = time.Duration(ticks.u) * unit
81+
u.Stime = time.Duration(ticks.s) * unit
82+
83+
if _, err := fmt.Fscanf(r, "%d %d",
84+
&ticks.u, &ticks.s); err != nil {
85+
return nil, errors.Trace(err)
86+
}
87+
u.Cutime = time.Duration(ticks.u) * unit
88+
u.Cstime = time.Duration(ticks.s) * unit
89+
90+
if _, err := fmt.Fscanf(r, "%d %d %d %d %d",
91+
&ignore.d, &ignore.d, &u.NumThreads, &ignore.d, &ignore.d); err != nil {
92+
return nil, errors.Trace(err)
93+
}
94+
if _, err := fmt.Fscanf(r, "%d %d",
95+
&u.VmSize, &u.VmRss); err != nil {
96+
return nil, errors.Trace(err)
97+
}
98+
u.VmRss *= int64(syscall.Getpagesize())
99+
return u, nil
100+
}

pkg/utils/usage_rusage.go

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
// Copyright 2016 CodisLabs. All Rights Reserved.
2+
// Licensed under the MIT (MIT-LICENSE.txt) license.
3+
4+
// +build !linux
5+
6+
package utils
7+
8+
import (
9+
"syscall"
10+
"time"
11+
12+
"github.com/CodisLabs/codis/pkg/utils/errors"
13+
)
14+
15+
/*
16+
#include <unistd.h>
17+
*/
18+
import "C"
19+
20+
type Usage struct {
21+
Utime time.Duration `json:"utime"`
22+
Stime time.Duration `json:"stime"`
23+
24+
MaxRss int64 `json:"max_rss"`
25+
Ixrss int64 `json:"ix_rss"`
26+
Idrss int64 `json:"id_rss"`
27+
Isrss int64 `json:"is_rss"`
28+
}
29+
30+
func (u *Usage) MemTotal() int64 {
31+
return u.Ixrss + u.Idrss + u.Isrss
32+
}
33+
34+
func (u *Usage) CPUTotal() time.Duration {
35+
return u.Utime + u.Stime
36+
}
37+
38+
func GetUsage() (*Usage, error) {
39+
var usage syscall.Rusage
40+
if err := syscall.Getrusage(syscall.RUSAGE_SELF, &usage); err != nil {
41+
return nil, errors.Trace(err)
42+
}
43+
u := &Usage{}
44+
u.Utime = time.Duration(usage.Utime.Nano())
45+
u.Stime = time.Duration(usage.Stime.Nano())
46+
47+
unit := 1024 * int64(C.sysconf(C._SC_CLK_TCK))
48+
49+
u.MaxRss = usage.Maxrss
50+
u.Ixrss = unit * usage.Ixrss
51+
u.Idrss = unit * usage.Idrss
52+
u.Isrss = unit * usage.Isrss
53+
return u, nil
54+
}

0 commit comments

Comments
 (0)