A package-level variable whose initializer calls sort.Strings is not evaluated at compile time. The initializer runs at startup instead.
Given this program:
package main
import (
"runtime"
"sort"
)
var words = []string{
"delta", "alpha", "echo", "charlie", "bravo",
"golf", "foxtrot", "india", "hotel",
}
// table is a package-level variable, so interp normally evaluates build() at
// compile time.
var table = build(words)
func build(w []string) []int32 {
sorted := append(make([]string, 0, len(w)), w...)
sort.Strings(sorted)
t := make([]int32, 4096)
for i, s := range sorted {
t[i] = int32(len(s))
}
return t
}
func main() {
var ms runtime.MemStats
runtime.ReadMemStats(&ms)
println("TotalAlloc:", int(ms.TotalAlloc))
println("len:", len(table))
}
The interp phase bails out because of the sort.Strings(sorted) call. Claude tells me it is because of the recursive pdqsort implementation in the standard library. Maybe!
If you swap it out for sort.Slice(sorted, func(i, j int) bool { return sorted[i] < sorted[j] } then it appears to be compiled in.
good TotalAlloc: 65584
bad TotalAlloc: 82040
I was able to reproduce this with both TinyGo 0.41.1 and 0.33.0.
A package-level variable whose initializer calls
sort.Stringsis not evaluated at compile time. The initializer runs at startup instead.Given this program:
The interp phase bails out because of the
sort.Strings(sorted)call. Claude tells me it is because of the recursive pdqsort implementation in the standard library. Maybe!If you swap it out for
sort.Slice(sorted, func(i, j int) bool { return sorted[i] < sorted[j] }then it appears to be compiled in.I was able to reproduce this with both TinyGo 0.41.1 and 0.33.0.