From c17b9e093d1b503ba91df1617c6ae2f4077d4224 Mon Sep 17 00:00:00 2001 From: Cameron Clark Date: Wed, 13 Aug 2025 12:52:39 +0100 Subject: [PATCH] perf(tspath): void []byte allocation in ToFileNameLowerCase MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace `for _, c := range []byte(fileName)` with direct byte indexing to iterate over the string without allocating a new []byte slice. This removes an unnecessary allocation in both the ASCII fast path check and the lowercasing loop, improving performance and reducing GC pressure. ``` │ bench-to-file-name-lower-case-main.txt │ bench-to-file-name-lower-case-cbdcb60a5.txt │ │ sec/op │ sec/op vs base │ ToFileNameLowerCase//path/to/file.ext-12 8.422n ± ∞ ¹ 8.508n ± ∞ ¹ ~ (p=0.151 n=5) ToFileNameLowerCase//PATH/TO/FILE.EXT-12 38.27n ± ∞ ¹ 38.27n ± ∞ ¹ ~ (p=0.730 n=5) ToFileNameLowerCase//path/to/FILE.EXT-12 41.08n ± ∞ ¹ 41.03n ± ∞ ¹ ~ (p=0.421 n=5) ToFileNameLowerCase//user/UserName/proje...etc-12 58.59n ± ∞ ¹ 58.32n ± ∞ ¹ ~ (p=0.841 n=5) ToFileNameLowerCase//user/UserName/proje...etc#01-12 161.1n ± ∞ ¹ 161.5n ± ∞ ¹ ~ (p=0.635 n=5) ToFileNameLowerCase//user/UserName/proje...etc#02-12 155.1n ± ∞ ¹ 154.1n ± ∞ ¹ ~ (p=0.595 n=5) ToFileNameLowerCase//user/UserName/proje...etc#03-12 139.5n ± ∞ ¹ 136.7n ± ∞ ¹ -2.01% (p=0.048 n=5) ToFileNameLowerCase/FoO/FoO/FoO/FoO/FoO/...etc-12 550.8n ± ∞ ¹ 548.7n ± ∞ ¹ ~ (p=0.841 n=5) geomean 78.82n 78.58n -0.30% ``` --- internal/tspath/path.go | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/internal/tspath/path.go b/internal/tspath/path.go index 1d74389169..43d7bb6ea4 100644 --- a/internal/tspath/path.go +++ b/internal/tspath/path.go @@ -583,7 +583,9 @@ func ToFileNameLowerCase(fileName string) string { ascii := true needsLower := false - for _, c := range []byte(fileName) { + fileNameLen := len(fileName) + for i := range fileNameLen { + c := fileName[i] if c >= 0x80 { ascii = false break @@ -596,8 +598,9 @@ func ToFileNameLowerCase(fileName string) string { if !needsLower { return fileName } - b := make([]byte, len(fileName)) - for i, c := range []byte(fileName) { + b := make([]byte, fileNameLen) + for i := range fileNameLen { + c := fileName[i] if 'A' <= c && c <= 'Z' { c += 'a' - 'A' // +32 }