Skip to content

Commit fab03ae

Browse files
committed
Bringing number of syscalls down in fs.getDistStatsMap()
1 parent 248756c commit fab03ae

File tree

2 files changed

+94
-48
lines changed

2 files changed

+94
-48
lines changed

fs/fs.go

Lines changed: 85 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,9 @@
1919
package fs
2020

2121
import (
22-
"bufio"
22+
"bytes"
2323
"fmt"
24+
"io"
2425
"os"
2526
"os/exec"
2627
"path"
@@ -57,6 +58,9 @@ const (
5758
// A pool for restricting the number of consecutive `du` and `find` tasks running.
5859
var pool = make(chan struct{}, maxConcurrentOps)
5960

61+
// bufSize control size of read buffer in getDiskStatsMap()
62+
var bufSize = 5000
63+
6064
func init() {
6165
for i := 0; i < maxConcurrentOps; i++ {
6266
releaseToken()
@@ -459,67 +463,100 @@ func getDiskStatsMap(diskStatsFile string) (map[string]DiskStats, error) {
459463
}
460464

461465
defer file.Close()
462-
scanner := bufio.NewScanner(file)
463466

464-
for scanner.Scan() {
465-
line := scanner.Text()
466-
words := strings.Fields(line)
467-
if !partitionRegex.MatchString(words[2]) {
468-
continue
467+
leftover := []byte{}
468+
const newline = 10
469+
for {
470+
buf := make([]byte, bufSize)
471+
count, err := file.Read(buf)
472+
buf = append(leftover, buf...)
473+
klog.V(10).Infof("read %d bytes in getDiskStatsMap()", count)
474+
if err == io.EOF {
475+
break
476+
}
477+
lines := bytes.Split(buf, []byte{newline})
478+
var skipLastLine bool
479+
if buf[len(buf)-1] != newline {
480+
skipLastLine = true
469481
}
470-
// 8 50 sdd2 40 0 280 223 7 0 22 108 0 330 330
471-
deviceName := path.Join("/dev", words[2])
472482

473-
var err error
474-
devInfo := make([]uint64, 2)
475-
for i := 0; i < len(devInfo); i++ {
476-
devInfo[i], err = strconv.ParseUint(words[i], 10, 64)
483+
for i, bLine := range lines {
484+
if len(bLine) == 0 {
485+
klog.V(10).Infof("skipping empty line in getDiskStatsMap() iteration %d", i)
486+
continue
487+
}
488+
if skipLastLine && i == len(lines)-1 {
489+
klog.V(10).Infof("skipping leftover line in getDiskStatsMap() iteration %d", i)
490+
continue
491+
}
492+
line := string(bLine)
493+
words := strings.Fields(line)
494+
495+
if !partitionRegex.MatchString(words[2]) {
496+
continue
497+
}
498+
// 8 50 sdd2 40 0 280 223 7 0 22 108 0 330 330
499+
deviceName := path.Join("/dev", words[2])
500+
501+
var err error
502+
devInfo := make([]uint64, 2)
503+
for i := 0; i < len(devInfo); i++ {
504+
devInfo[i], err = strconv.ParseUint(words[i], 10, 64)
505+
if err != nil {
506+
return nil, err
507+
}
508+
}
509+
510+
wordLength := len(words)
511+
offset := 3
512+
var stats = make([]uint64, wordLength-offset)
513+
if len(stats) < 11 {
514+
return nil, fmt.Errorf("could not parse all 11 columns of /proc/diskstats")
515+
}
516+
for i := offset; i < wordLength; i++ {
517+
stats[i-offset], err = strconv.ParseUint(words[i], 10, 64)
518+
if err != nil {
519+
return nil, err
520+
}
521+
}
522+
523+
major64, err := strconv.ParseUint(words[0], 10, 64)
477524
if err != nil {
478525
return nil, err
479526
}
480-
}
481527

482-
wordLength := len(words)
483-
offset := 3
484-
var stats = make([]uint64, wordLength-offset)
485-
if len(stats) < 11 {
486-
return nil, fmt.Errorf("could not parse all 11 columns of /proc/diskstats")
487-
}
488-
for i := offset; i < wordLength; i++ {
489-
stats[i-offset], err = strconv.ParseUint(words[i], 10, 64)
528+
minor64, err := strconv.ParseUint(words[1], 10, 64)
490529
if err != nil {
491530
return nil, err
492531
}
532+
533+
diskStats := DiskStats{
534+
MajorNum: devInfo[0],
535+
MinorNum: devInfo[1],
536+
ReadsCompleted: stats[0],
537+
ReadsMerged: stats[1],
538+
SectorsRead: stats[2],
539+
ReadTime: stats[3],
540+
WritesCompleted: stats[4],
541+
WritesMerged: stats[5],
542+
SectorsWritten: stats[6],
543+
WriteTime: stats[7],
544+
IoInProgress: stats[8],
545+
IoTime: stats[9],
546+
WeightedIoTime: stats[10],
547+
Major: major64,
548+
Minor: minor64,
549+
}
550+
diskStatsMap[deviceName] = diskStats
493551
}
494552

495-
major64, err := strconv.ParseUint(words[0], 10, 64)
496-
if err != nil {
497-
return nil, err
553+
if buf[len(buf)-1] != newline {
554+
leftover = lines[len(lines)-1]
555+
klog.V(10).Info("saving leftover line %q", leftover)
556+
} else {
557+
leftover = []byte{}
498558
}
499559

500-
minor64, err := strconv.ParseUint(words[1], 10, 64)
501-
if err != nil {
502-
return nil, err
503-
}
504-
505-
diskStats := DiskStats{
506-
MajorNum: devInfo[0],
507-
MinorNum: devInfo[1],
508-
ReadsCompleted: stats[0],
509-
ReadsMerged: stats[1],
510-
SectorsRead: stats[2],
511-
ReadTime: stats[3],
512-
WritesCompleted: stats[4],
513-
WritesMerged: stats[5],
514-
SectorsWritten: stats[6],
515-
WriteTime: stats[7],
516-
IoInProgress: stats[8],
517-
IoTime: stats[9],
518-
WeightedIoTime: stats[10],
519-
Major: major64,
520-
Minor: minor64,
521-
}
522-
diskStatsMap[deviceName] = diskStats
523560
}
524561
return diskStatsMap, nil
525562
}

fs/fs_test.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,9 @@ func TestMountInfoFromDir(t *testing.T) {
4040
}
4141

4242
func TestGetDiskStatsMap(t *testing.T) {
43+
origBufSize := bufSize
44+
bufSize = 100
45+
defer func() { bufSize = origBufSize }()
4346
diskStatsMap, err := getDiskStatsMap("test_resources/diskstats")
4447
if err != nil {
4548
t.Errorf("Error calling getDiskStatsMap %s", err)
@@ -92,6 +95,9 @@ func TestGetDiskStatsMap(t *testing.T) {
9295
}
9396

9497
func TestGetDiskStatsMapMajorMinorNum(t *testing.T) {
98+
origBufSize := bufSize
99+
bufSize = 100
100+
defer func() { bufSize = origBufSize }()
95101
diskStatsMap, err := getDiskStatsMap("test_resources/diskstats")
96102
if err != nil {
97103
t.Errorf("Error calling getDiskStatsMap %s", err)
@@ -108,6 +114,9 @@ func TestGetDiskStatsMapMajorMinorNum(t *testing.T) {
108114
}
109115

110116
func TestFileNotExist(t *testing.T) {
117+
origBufSize := bufSize
118+
bufSize = 100
119+
defer func() { bufSize = origBufSize }()
111120
_, err := getDiskStatsMap("/file_does_not_exist")
112121
if err != nil {
113122
t.Fatalf("getDiskStatsMap must not error for absent file: %s", err)

0 commit comments

Comments
 (0)