Skip to content

cmd/compile: range loop with large element has a significant cost #59706

@egonelbre

Description

@egonelbre

What version of Go are you using (go version)?

$ go version
go version devel go1.21-969ab34e46 Wed Apr 19 02:10:00 2023 +0000 windows/amd64

Does this issue reproduce with the latest release?

Yes.

What did you do?

Here's a benchmark of two approaches of writing slices.Index:

package main

import "testing"

type Large [4 * 1024]byte

const N = 1024

func IndexA(s []Large, v Large) int {
	for i, vs := range s {
		if v == vs {
			return i
		}
	}
	return -1
}

func IndexB(s []Large, v Large) int {
	for i := range s {
		if v == s[i] {
			return i
		}
	}
	return -1
}

func BenchmarkA_Large(b *testing.B) {
	elements := make([]Large, N)
	for k := 0; k < b.N; k++ {
		IndexA(elements, Large{1})
	}
}

func BenchmarkB_Large(b *testing.B) {
	elements := make([]Large, N)
	for k := 0; k < b.N; k++ {
		IndexB(elements, Large{1})
	}
}

Results:

BenchmarkA_Large-32         3129            352215 ns/op
BenchmarkB_Large-32       256124              4516 ns/op

I would have expected the results to be approximately the same, however, there's a significant cost to using for i, v := range s loop.

As far as I was able to tell, the slower implementation ends up making more copies of the v.

I made a quick fix for slices package for the time being https://go-review.googlesource.com/c/go/+/486235.

Metadata

Metadata

Assignees

No one assigned

    Labels

    NeedsInvestigationSomeone must examine and confirm this is a valid issue and not a duplicate of an existing one.Performancecompiler/runtimeIssues related to the Go compiler and/or runtime.

    Type

    No type

    Projects

    Status

    Todo

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions