Skip to content

Commit defb1cc

Browse files
committed
libct/cg/dev: optimize and test findDeviceGroup
1. Use strings.TrimPrefix instead of fmt.Sscanf and simplify the code. 2. Add a test case and a benchmark. The benchmark shows some improvement, compared to the old implementation: name old time/op new time/op delta FindDeviceGroup-4 39.7µs ± 2% 26.8µs ± 2% -32.63% (p=0.008 n=5+5) name old alloc/op new alloc/op delta FindDeviceGroup-4 6.08kB ± 0% 4.23kB ± 0% -30.39% (p=0.008 n=5+5) name old allocs/op new allocs/op delta FindDeviceGroup-4 117 ± 0% 6 ± 0% -94.87% (p=0.008 n=5+5) Signed-off-by: Kir Kolyshkin <[email protected]>
1 parent 39fe1c3 commit defb1cc

File tree

2 files changed

+32
-15
lines changed

2 files changed

+32
-15
lines changed

libcontainer/cgroups/devices/systemd.go

Lines changed: 5 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@ package devices
22

33
import (
44
"bufio"
5-
"errors"
65
"fmt"
76
"os"
7+
"strconv"
88
"strings"
99

1010
systemdDbus "github.com/coreos/go-systemd/v22/dbus"
@@ -181,6 +181,7 @@ func findDeviceGroup(ruleType devices.Type, ruleMajor int64) (string, error) {
181181
if err != nil {
182182
return "", err
183183
}
184+
ruleMajorStr := strconv.FormatInt(ruleMajor, 10) + " "
184185

185186
scanner := bufio.NewScanner(fh)
186187
var currentType devices.Type
@@ -205,20 +206,9 @@ func findDeviceGroup(ruleType devices.Type, ruleMajor int64) (string, error) {
205206
continue
206207
}
207208

208-
// Parse out the (major, name).
209-
var (
210-
currMajor int64
211-
currName string
212-
)
213-
if n, err := fmt.Sscanf(line, "%d %s", &currMajor, &currName); err != nil || n != 2 {
214-
if err == nil {
215-
err = errors.New("wrong number of fields")
216-
}
217-
return "", fmt.Errorf("scan /proc/devices line %q: %w", line, err)
218-
}
219-
220-
if currMajor == ruleMajor {
221-
return prefix + currName, nil
209+
group := strings.TrimPrefix(line, ruleMajorStr)
210+
if len(group) < len(line) { // got it
211+
return prefix + group, nil
222212
}
223213
}
224214
if err := scanner.Err(); err != nil {

libcontainer/cgroups/devices/systemd_test.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package devices
22

33
import (
44
"bytes"
5+
"fmt"
56
"os"
67
"os/exec"
78
"strings"
@@ -240,6 +241,32 @@ func TestSkipDevicesFalse(t *testing.T) {
240241
})
241242
}
242243

244+
func testFindDeviceGroup() error {
245+
const (
246+
major = 136
247+
group = "char-pts"
248+
)
249+
res, err := findDeviceGroup(devices.CharDevice, major)
250+
if res != group || err != nil {
251+
return fmt.Errorf("expected %v, nil, got %v, %w", group, res, err)
252+
}
253+
return nil
254+
}
255+
256+
func TestFindDeviceGroup(t *testing.T) {
257+
if err := testFindDeviceGroup(); err != nil {
258+
t.Fatal(err)
259+
}
260+
}
261+
262+
func BenchmarkFindDeviceGroup(b *testing.B) {
263+
for i := 0; i < b.N; i++ {
264+
if err := testFindDeviceGroup(); err != nil {
265+
b.Fatal(err)
266+
}
267+
}
268+
}
269+
243270
func newManager(t *testing.T, config *configs.Cgroup) (m cgroups.Manager) {
244271
t.Helper()
245272
var err error

0 commit comments

Comments
 (0)