Skip to content

interp gives up on sort.Strings but works with sort.Slice #5583

Description

@joeshaw

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions