Skip to content

Commit

Permalink
container/common: Replace readUInt64 with optimized version
Browse files Browse the repository at this point in the history
This patch replaces the `readUint64` function with one that optimizes
for reading uint64s from files only. It prevents unnecessary calls to
`.Stat` because a valid uint64 can be 20 characters at most anyway. It
also avoids a few allocations.

Overall, benchmarking has shown to reduce the total CPU time by ~15%,
which given a total usage of roughly 3% in the entire kubelet, this
means we're reducing the kubelet baseline CPU by about ~0.45%.
  • Loading branch information
brancz committed Oct 6, 2023
1 parent fb37bb8 commit 324a907
Showing 1 changed file with 42 additions and 4 deletions.
46 changes: 42 additions & 4 deletions container/common/helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@
package common

import (
"bytes"
"fmt"
"io"
"math"
"os"
"path"
Expand Down Expand Up @@ -277,15 +279,16 @@ func parseUint64String(strValue string) uint64 {
}

func readUInt64(dirpath string, file string) uint64 {
out := readString(dirpath, file)
if out == "max" {
fullPath := path.Join(dirpath, file)
out := readNBytesFromFile(fullPath, 20)
if bytes.Equal(out, []byte("max")) {
return math.MaxUint64
}
if out == "" {
if len(out) == 0 {
return 0
}

val, err := strconv.ParseUint(out, 10, 64)
val, err := parseBase10Uint64(out)
if err != nil {
klog.Errorf("readUInt64: Failed to parse int %q from file %q: %s", out, path.Join(dirpath, file), err)
return 0
Expand All @@ -294,6 +297,41 @@ func readUInt64(dirpath string, file string) uint64 {
return val
}

func parseBase10Uint64(buf []byte) (uint64, error) {
res := uint64(0)

for i, b := range buf {
if b < '0' || b > '9' {
return 0, fmt.Errorf("parseBase10Uint64: invalid byte %q at position %d", b, i)
}
res += uint64(b-'0') * uint64(math.Pow10(len(buf)-i-1))
}

return res, nil
}

func readNBytesFromFile(file string, i int) []byte {
f, err := os.Open(file)
if err != nil {
// Ignore non-existent files
if !os.IsNotExist(err) {
klog.Warningf("readNBytesFromFile: Failed to open %q: %s", file, err)
}
return nil
}
defer f.Close()

buf := make([]byte, i)
n, err := io.ReadFull(f, buf)
if err != nil {
if err != io.EOF && err != io.ErrUnexpectedEOF {
klog.Warningf("readNBytesFromFile: Failed to read %q: %s", file, err)
}
}

return bytes.TrimSpace(buf[:n])
}

// Lists all directories under "path" and outputs the results as children of "parent".
func ListDirectories(dirpath string, parent string, recursive bool, output map[string]struct{}) error {
buf := make([]byte, godirwalk.MinimumScratchBufferSize)
Expand Down

0 comments on commit 324a907

Please sign in to comment.