Skip to content

Commit f4638b4

Browse files
authored
Merge pull request #291 from manugupt1/improve-perf
Improve performance by for pid stats (cgroups1) re-using readuint
2 parents 0f00bce + 0895e99 commit f4638b4

File tree

4 files changed

+77
-11
lines changed

4 files changed

+77
-11
lines changed

cgroup1/pids.go

+1-8
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ import (
2020
"os"
2121
"path/filepath"
2222
"strconv"
23-
"strings"
2423

2524
v1 "github.com/containerd/cgroups/v3/cgroup1/stats"
2625
specs "github.com/opencontainers/runtime-spec/specs-go"
@@ -67,16 +66,10 @@ func (p *pidsController) Stat(path string, stats *v1.Metrics) error {
6766
if err != nil {
6867
return err
6968
}
70-
var max uint64
71-
maxData, err := os.ReadFile(filepath.Join(p.Path(path), "pids.max"))
69+
max, err := readUint(filepath.Join(p.Path(path), "pids.max"))
7270
if err != nil {
7371
return err
7472
}
75-
if maxS := strings.TrimSpace(string(maxData)); maxS != "max" {
76-
if max, err = parseUint(maxS, 10, 64); err != nil {
77-
return err
78-
}
79-
}
8073
stats.Pids = &v1.PidsStat{
8174
Current: current,
8275
Limit: max,

cgroup1/pids_test.go

+47
Original file line numberDiff line numberDiff line change
@@ -186,3 +186,50 @@ func TestPidsOverflowMax(t *testing.T) {
186186
t.Fatal("expected not nil err")
187187
}
188188
}
189+
190+
func BenchmarkTestPids(b *testing.B) {
191+
192+
mock, err := newMock(b)
193+
if err != nil {
194+
b.Fatal(err)
195+
}
196+
defer func() {
197+
if err := mock.delete(); err != nil {
198+
b.Errorf("failed delete: %v", err)
199+
}
200+
}()
201+
202+
pids := NewPids(mock.root)
203+
if pids == nil {
204+
b.Fatal("pids is nil")
205+
}
206+
resources := specs.LinuxResources{
207+
Pids: &specs.LinuxPids{
208+
Limit: 10,
209+
},
210+
}
211+
212+
err = pids.Create("test", &resources)
213+
if err != nil {
214+
b.Fatal(err)
215+
}
216+
217+
current := filepath.Join(mock.root, "pids", "test", "pids.current")
218+
if err = os.WriteFile(
219+
current,
220+
[]byte(strconv.Itoa(5)),
221+
defaultFilePerm,
222+
); err != nil {
223+
b.Fatal(err)
224+
}
225+
226+
b.ReportAllocs()
227+
228+
for i := 0; i < b.N; i++ {
229+
metrics := v1.Metrics{}
230+
err = pids.Stat("test", &metrics)
231+
if err != nil {
232+
b.Fatal(err)
233+
}
234+
}
235+
}

cgroup1/utils.go

+10-3
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ package cgroup1
1818

1919
import (
2020
"bufio"
21+
"bytes"
2122
"fmt"
2223
"os"
2324
"path/filepath"
@@ -137,13 +138,19 @@ func readUint(path string) (uint64, error) {
137138
}
138139
defer f.Close()
139140

140-
b := make([]byte, 128) // Chose 128 as some files have leading/trailing whitespaces and alignment
141+
// We should only need 20 bytes for the max uint64, but for a nice power of 2
142+
// lets use 32.
143+
b := make([]byte, 32)
141144
n, err := f.Read(b)
142145
if err != nil {
143146
return 0, err
144147
}
145-
146-
return parseUint(strings.TrimSpace(string(b[:n])), 10, 64)
148+
s := string(bytes.TrimSpace(b[:n]))
149+
if s == "max" {
150+
// Return 0 for the max value to maintain backward compatibility.
151+
return 0, nil
152+
}
153+
return parseUint(s, 10, 64)
147154
}
148155

149156
func parseUint(s string, base, bitSize int) (uint64, error) {

cgroup1/utils_test.go

+19
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
package cgroup1
1818

1919
import (
20+
"os"
21+
"path/filepath"
2022
"testing"
2123
)
2224

@@ -30,3 +32,20 @@ func BenchmarkReaduint64(b *testing.B) {
3032
}
3133
}
3234
}
35+
36+
func TestReadUint(t *testing.T) {
37+
tDir := t.TempDir()
38+
pidsmax := filepath.Join(tDir, "pids.max")
39+
err := os.WriteFile(pidsmax, []byte("max"), 0644)
40+
if err != nil {
41+
t.Fatal(err)
42+
}
43+
max, err := readUint(pidsmax)
44+
if err != nil {
45+
t.Fatal(err)
46+
}
47+
// test for backwards compatibility
48+
if max != 0 {
49+
t.Fail()
50+
}
51+
}

0 commit comments

Comments
 (0)