Skip to content

Commit

Permalink
readConfig,loadLabels: stop using regex
Browse files Browse the repository at this point in the history
Using a globally initialized regex incurs some overhead during package
initialization, which is noticeable for all other packages importing it.

Besides, there's no need to use regex to perform key=value split.

Rewrite both functions without using regex, and add benchmarks, which
show that the new code is faster:

name          old time/op    new time/op    delta
ReadConfig-4    4.86µs ± 1%    3.46µs ± 2%  -28.82%  (p=0.002 n=6+6)
LoadLabels-4    12.7µs ± 3%     6.8µs ± 1%  -46.24%  (p=0.002 n=6+6)

name          old alloc/op   new alloc/op   delta
ReadConfig-4    5.08kB ± 0%    4.35kB ± 0%  -14.33%  (p=0.002 n=6+6)
LoadLabels-4    6.49kB ± 0%    6.10kB ± 0%   -6.07%  (p=0.000 n=6+5)

name          old allocs/op  new allocs/op  delta
ReadConfig-4      20.0 ± 0%       8.0 ± 0%  -60.00%  (p=0.002 n=6+6)
LoadLabels-4      45.0 ± 0%      45.0 ± 0%     ~     (all equal)

Besides, the init overhead is eliminated:

Before:
init github.com/opencontainers/selinux/go-selinux @2.4 ms, 0.088 ms clock, 5016 bytes, 72 allocs

After:
init github.com/opencontainers/selinux/go-selinux @2.9 ms, 0.001 ms clock, 160 bytes, 8 allocs

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
  • Loading branch information
kolyshkin committed Sep 8, 2021
1 parent 397b931 commit 9bb3eeb
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 12 deletions.
25 changes: 13 additions & 12 deletions go-selinux/selinux_linux.go
Expand Up @@ -12,7 +12,6 @@ import (
"os"
"path"
"path/filepath"
"regexp"
"strconv"
"strings"
"sync"
Expand Down Expand Up @@ -68,7 +67,6 @@ const (
)

var (
assignRegex = regexp.MustCompile(`^([^=]+)=(.*)$`)
readOnlyFileLabel string
state = selinuxState{
mcsList: make(map[string]bool),
Expand Down Expand Up @@ -237,7 +235,7 @@ func readConfig(target string) string {
scanner := bufio.NewScanner(in)

for scanner.Scan() {
line := strings.TrimSpace(scanner.Text())
line := bytes.TrimSpace(scanner.Bytes())
if len(line) == 0 {
// Skip blank lines
continue
Expand All @@ -246,11 +244,12 @@ func readConfig(target string) string {
// Skip comments
continue
}
if groups := assignRegex.FindStringSubmatch(line); groups != nil {
key, val := strings.TrimSpace(groups[1]), strings.TrimSpace(groups[2])
if key == target {
return strings.Trim(val, "\"")
}
fields := bytes.SplitN(line, []byte{'='}, 2)
if len(fields) != 2 {
continue
}
if bytes.Equal(fields[0], []byte(target)) {
return string(bytes.Trim(fields[1], `"`))
}
}
return ""
Expand Down Expand Up @@ -920,7 +919,7 @@ func loadLabels() {
scanner := bufio.NewScanner(in)

for scanner.Scan() {
line := strings.TrimSpace(scanner.Text())
line := bytes.TrimSpace(scanner.Bytes())
if len(line) == 0 {
// Skip blank lines
continue
Expand All @@ -929,10 +928,12 @@ func loadLabels() {
// Skip comments
continue
}
if groups := assignRegex.FindStringSubmatch(line); groups != nil {
key, val := strings.TrimSpace(groups[1]), strings.TrimSpace(groups[2])
labels[key] = strings.Trim(val, "\"")
fields := bytes.SplitN(line, []byte{'='}, 2)
if len(fields) != 2 {
continue
}
key, val := bytes.TrimSpace(fields[0]), bytes.TrimSpace(fields[1])
labels[string(key)] = string(bytes.Trim(val, `"`))
}

con, _ := NewContext(labels["file"])
Expand Down
14 changes: 14 additions & 0 deletions go-selinux/selinux_linux_test.go
Expand Up @@ -507,3 +507,17 @@ func BenchmarkChcon(b *testing.B) {
}
}
}

func BenchmarkReadConfig(b *testing.B) {
str := ""
for n := 0; n < b.N; n++ {
str = readConfig(selinuxTypeTag)
}
b.Log(str)
}

func BenchmarkLoadLabels(b *testing.B) {
for n := 0; n < b.N; n++ {
loadLabels()
}
}

0 comments on commit 9bb3eeb

Please sign in to comment.