Skip to content

Commit

Permalink
Remove unsafe zero copy calls from parseStatusLine and parseStatConte…
Browse files Browse the repository at this point in the history
…nt as Go has improved escape analysis to avoid the byte to string copy.
  • Loading branch information
wiyu committed Nov 29, 2023
1 parent 5222280 commit 334852a
Showing 1 changed file with 10 additions and 26 deletions.
36 changes: 10 additions & 26 deletions pkg/process/procutil/process_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ import (
"syscall"
"time"
"unicode"
"unsafe"

"go.uber.org/atomic"

Expand Down Expand Up @@ -533,7 +532,7 @@ func (p *probe) parseStatusKV(key, value []byte, sInfo *statusInfo) {
values := bytes.Fields(value)
ints := make([]int32, 0, len(values))
for _, v := range values {
if i, err := parseBytesToInt(v, 10, 32); err == nil {
if i, err := strconv.ParseInt(string(v), 10, 32); err == nil {
ints = append(ints, int32(i))
}
}
Expand All @@ -545,15 +544,15 @@ func (p *probe) parseStatusKV(key, value []byte, sInfo *statusInfo) {
case bytes.Equal(key, keyNSpid):
values := bytes.Split(value, []byte("\t"))
// only report process namespaced PID
if v, err := parseBytesToInt(values[len(values)-1], 10, 32); err == nil {
if v, err := strconv.ParseInt(string(values[len(values)-1]), 10, 32); err == nil {
sInfo.nspid = int32(v)
}
case bytes.Equal(key, keyThreads):
if v, err := parseBytesToInt(value, 10, 32); err == nil {
if v, err := strconv.ParseInt(string(value), 10, 32); err == nil {
sInfo.numThreads = int32(v)
}
case bytes.Equal(key, keyVoluntaryCtxtSwitches), bytes.Equal(key, keyNonvoluntaryCtxtSwitches):
if v, err := parseBytesToInt(value, 10, 64); err == nil {
if v, err := strconv.ParseInt(string(value), 10, 64); err == nil {
if key[0] == 'v' {
sInfo.ctxSwitches.Voluntary = v
} else {
Expand All @@ -565,25 +564,10 @@ func (p *probe) parseStatusKV(key, value []byte, sInfo *statusInfo) {
}
}

func parseBytesToInt(buf []byte, base int, bitSize int) (int64, error) {
// Safety: We are not modifying the contents of the byte slice.
return strconv.ParseInt(*(*string)(unsafe.Pointer(&buf)), base, bitSize)
}

func parseBytesToUint(buf []byte, base int, bitSize int) (uint64, error) {
// Safety: We are not modifying the contents of the byte slice.
return strconv.ParseUint(*(*string)(unsafe.Pointer(&buf)), base, bitSize)
}

func parseBytesToFloat(buf []byte, bitSize int) (float64, error) {
// Safety: We are not modifying the contents of the byte slice.
return strconv.ParseFloat(*(*string)(unsafe.Pointer(&buf)), bitSize)
}

func parseMemInfo(value, key []byte, memInfo *MemoryInfoStat) {
value = bytes.TrimSuffix(value, []byte("kB"))
value = bytes.TrimSpace(value)
if v, err := parseBytesToUint(value, 10, 64); err == nil {
if v, err := strconv.ParseUint(string(value), 10, 64); err == nil {
v *= 1024
switch key[3] { // Using the fourth byte to differentiate between RSS, Size, and Swap
case 'S': // VmRSS
Expand Down Expand Up @@ -634,23 +618,23 @@ func (p *probe) parseStatContent(statContent []byte, sInfo *statInfo, pid int32,
if !prevCharIsSpace {
switch spaces {
case 2:
if ppid, err := parseBytesToInt(buffer, 10, 32); err == nil {
if ppid, err := strconv.ParseInt(string(buffer), 10, 32); err == nil {
sInfo.ppid = int32(ppid)
}
case 7:
if flags, err := parseBytesToUint(buffer, 10, 32); err == nil {
if flags, err := strconv.ParseUint(string(buffer), 10, 32); err == nil {
sInfo.flags = uint32(flags)
}
case 12:
if utime, err := parseBytesToFloat(buffer, 64); err == nil {
if utime, err := strconv.ParseFloat(string(buffer), 64); err == nil {
sInfo.cpuStat.User = utime / p.clockTicks
}
case 13:
if stime, err := parseBytesToFloat(buffer, 64); err == nil {
if stime, err := strconv.ParseFloat(string(buffer), 64); err == nil {
sInfo.cpuStat.System = stime / p.clockTicks
}
case 20:
if t, err := parseBytesToUint(buffer, 10, 64); err == nil {
if t, err := strconv.ParseUint(string(buffer), 10, 64); err == nil {
ctime := (t / uint64(p.clockTicks)) + p.bootTime.Load()
// convert create time into milliseconds
sInfo.createTime = int64(ctime * 1000)
Expand Down

0 comments on commit 334852a

Please sign in to comment.