Skip to content

Commit

Permalink
remove string copies from cgo ref pool
Browse files Browse the repository at this point in the history
Signed-off-by: Eliott Bouhana <[email protected]>
  • Loading branch information
eliottness committed Nov 2, 2023
1 parent 278d12b commit 462a2c1
Show file tree
Hide file tree
Showing 3 changed files with 18 additions and 19 deletions.
31 changes: 12 additions & 19 deletions cgo_ref_pool.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import (
// wafObject are either arrays (for maps, structs and arrays) or string (for all ints, booleans and strings),
// we can store 2 slices of arrays and use runtime.KeepAlive in each code path to protect them from the GC.
type cgoRefPool struct {
stringRefs [][]byte
stringRefs []string
arrayRefs [][]wafObject
}

Expand All @@ -30,12 +30,9 @@ func (refPool *cgoRefPool) append(newRefs cgoRefPool) {
}

func (refPool *cgoRefPool) AllocCString(str string) uintptr {
goArray := make([]byte, len(str)+1)
copy(goArray, str)
refPool.stringRefs = append(refPool.stringRefs, goArray)
goArray[len(str)] = 0 // Null termination byte for C strings

return sliceToUintptr(goArray)
nullTerminated := str + "\x00"
refPool.stringRefs = append(refPool.stringRefs, nullTerminated)
return nativeStringUnwrap(nullTerminated).Data
}

func (refPool *cgoRefPool) AllocWafString(obj *wafObject, str string) {
Expand All @@ -47,12 +44,10 @@ func (refPool *cgoRefPool) AllocWafString(obj *wafObject, str string) {
return
}

goArray := make([]byte, len(str))
copy(goArray, str)
refPool.stringRefs = append(refPool.stringRefs, goArray)

obj.value = sliceToUintptr(goArray)
obj.nbEntries = uint64(len(goArray))
refPool.stringRefs = append(refPool.stringRefs, str)
stringHeader := nativeStringUnwrap(str)
obj.value = stringHeader.Data
obj.nbEntries = uint64(stringHeader.Len)
}

func (refPool *cgoRefPool) AllocWafArray(obj *wafObject, typ wafObjectType, size uint64) []wafObject {
Expand Down Expand Up @@ -81,10 +76,8 @@ func (refPool *cgoRefPool) AllocWafMapKey(obj *wafObject, str string) {
return
}

goArray := make([]byte, len(str))
copy(goArray, str)
refPool.stringRefs = append(refPool.stringRefs, goArray)

obj.parameterName = sliceToUintptr(goArray)
obj.parameterNameLength = uint64(len(goArray))
refPool.stringRefs = append(refPool.stringRefs, str)
stringHeader := nativeStringUnwrap(str)
obj.parameterName = stringHeader.Data
obj.parameterNameLength = uint64(stringHeader.Len)
}
5 changes: 5 additions & 0 deletions ctypes.go
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,11 @@ func gostring(ptr *byte) string {
return string(unsafe.Slice(ptr, length))
}

// nativeStringUnwrap cast a native string type into it's runtime value. Exported as the struct reflect.StringHeader
func nativeStringUnwrap(str string) reflect.StringHeader {
return *(*reflect.StringHeader)(unsafe.Pointer(&str))
}

func gostringSized(ptr *byte, size uint64) string {
if ptr == nil {
return ""
Expand Down
1 change: 1 addition & 0 deletions waf_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1453,6 +1453,7 @@ func BenchmarkEncoder(b *testing.B) {
containerMaxSize: 100,
}
b.Run(fmt.Sprintf("%d", l), func(b *testing.B) {
b.ReportAllocs()
str := fullstr[:l]
slice := []string{str, str, str, str, str, str, str, str, str, str}
data := map[string]interface{}{
Expand Down

0 comments on commit 462a2c1

Please sign in to comment.