Small improvements for varfmt

This commit is contained in:
Egor 2024-06-03 20:56:45 +03:00
parent bfb0daa1ef
commit 4bd325a744

View file

@ -17,17 +17,18 @@ func Sprintf(format string, args ...any) string {
// init output strings.Builder and num rune buffer // init output strings.Builder and num rune buffer
// cant use strings.Builder for storing num since // cant use strings.Builder for storing num since
// builder can't clear its contents without reallocating // builder can't clear its contents without reallocating
output, num := strings.Builder{}, make([]rune, 0, 1) output, num := strings.Builder{}, make([]rune, 0, 2) // first alloc here
// convert args slice to strArgs string slice // convert args slice to strArgs string slice
strArgs, maxLen := make([]string, len(args), cap(args)), 0 strArgs, maxLen := make([]string, len(args), cap(args)), 0 // second alloc here
for i, arg := range args { for i, arg := range args {
strArgs[i] = fmt.Sprint(arg) strArgs[i] = fmt.Sprint(arg) // third and other allocs happen here
// could be further optimized
if len(strArgs[i]) > maxLen { if len(strArgs[i]) > maxLen {
maxLen = len(strArgs[i]) maxLen = len(strArgs[i])
} }
} }
// allocate maximum possible length of the resulting string // allocate maximum possible length of the resulting string
output.Grow(len(format) + len(args)*maxLen) output.Grow(len(format) + len(args)*maxLen) // third alloc here
start, argIndex := 0, 0 start, argIndex := 0, 0
// decode runes one by one // decode runes one by one
for start < len(format) { for start < len(format) {
@ -46,7 +47,7 @@ func Sprintf(format string, args ...any) string {
// append new rune if the number is bigger // append new rune if the number is bigger
// than the current buffer // than the current buffer
if numLength >= len(num) { if numLength >= len(num) {
num = append(num, r) num = append(num, r) // further allocs happen here
} else { } else {
num[numLength] = r num[numLength] = r
} }