Description
fixStringEncodedNumber allocates a new []byte slice and copies the entire data buffer for every regex match found. For data with many string-encoded numbers, this results in O(n²) memory allocation and copying behavior.
Evidence
File: pkg/codec/echoreplay.go:308-330
func fixStringEncodedNumber(data []byte) []byte {
// For each match:
// - allocates new []byte with make()
// - copies prefix + replacement + suffix
// - repeats for next match on the new allocation
}
Each match triggers a full-buffer copy. With hundreds of matches per frame (common in Echo VR replay data with many numeric fields), this becomes a significant hot path.
Impact
Performance degradation during conversion. For frames with many string-encoded numbers, the quadratic allocation pattern causes excessive GC pressure and CPU usage. This is measurable on large tape files.
Suggested Fix
Use bytes.Buffer or strings.Builder with a single pass, or use regexp.ReplaceAllFunc which handles the iteration internally with fewer allocations:
func fixStringEncodedNumber(data []byte) []byte {
return re.ReplaceAllFunc(data, func(match []byte) []byte {
// strip quotes from the number
return match[1 : len(match)-1]
})
}
🤖 Filed by Metis
Description
fixStringEncodedNumberallocates a new[]byteslice and copies the entire data buffer for every regex match found. For data with many string-encoded numbers, this results in O(n²) memory allocation and copying behavior.Evidence
File:
pkg/codec/echoreplay.go:308-330Each match triggers a full-buffer copy. With hundreds of matches per frame (common in Echo VR replay data with many numeric fields), this becomes a significant hot path.
Impact
Performance degradation during conversion. For frames with many string-encoded numbers, the quadratic allocation pattern causes excessive GC pressure and CPU usage. This is measurable on large tape files.
Suggested Fix
Use
bytes.Bufferorstrings.Builderwith a single pass, or useregexp.ReplaceAllFuncwhich handles the iteration internally with fewer allocations:🤖 Filed by Metis