Skip to content

cmd/compile: significant performance difference between 'strs[i] == str' and 'str == strs[i]'" #74471

Open
@Billdex

Description

@Billdex

Go version

go 1.24.1
darwin/arm64
Apple M1

Summary

I'm working on a performance optimization in our business logic and noticed a significant performance difference when swapping the strings on either side of an equality operator. After simplifying the logic to a contains function, I was able to reproduce the behavior. Below are the sample code and benchmarks

Sample Code

var containsSlice = func() []string {
    return []string{
        "12312312",    
        "abcsdsfw",
        "abcdefgh",
        "qereqwre",
        "gwertdsg",
        "hellowod",
        "iamgroot",
        "theiswer",
        "dg323sdf",
        "gadsewwe",
        "g42dg4t3",
        "4hre2323",
        "23eg4325",
        "13234234",
        "32dfgsdg",
        "23fgre34",
        "43rerrer",
        "hh2s2443",
        "hhwesded",
        "1swdf23d",
        "gwcdrwer",
        "bfgwertd",
        "badgwe3g",
        "lhoejyop",
    }
}()

func containsStringA(strs []string, str string) bool {
    for i := range strs {
        if strs[i] == str {
            return true
        }
    }
    return false
}

func containsStringB(strs []string, str string) bool {
    for i := range strs {
        if str == strs[i] {
            return true
        }
    }
    return false
}

func BenchmarkContainsStringA(b *testing.B) {
    for n := 0; n <= b.N; n++ {
        containsStringA(containsSlice, "lhoejyop")
    }
}

func BenchmarkContainsStringB(b *testing.B) {
    for n := 0; n <= b.N; n++ {
        containsStringB(containsSlice, "lhoejyop")
    }
}

Benchmark Result

goos: darwin
goarch: arm64
pkg: go-playground/simple
cpu: Apple M1
BenchmarkContainsStringA-8      19314198                61.63 ns/op
BenchmarkContainsStringB-8      72874310                16.04 ns/op

Swapping the string comparison order (strs[i] == str ➔ str == strs[i]) results in ~4x performance improvement (61.63 ns/op → 16.04 ns/op)
Why does operand ordering cause performance divergence when both implementations are logically equivalent?

Metadata

Metadata

Assignees

No one assigned

    Labels

    BugReportIssues describing a possible bug in the Go implementation.Performancecompiler/runtimeIssues related to the Go compiler and/or runtime.help wanted

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions