tinygo icon indicating copy to clipboard operation
tinygo copied to clipboard

`bytes.Equal` shouldn't allocate

Open dgryski opened this issue 1 year ago • 5 comments

TinyGo uses the bytes package from upstream Go.

// Equal reports whether a and b
// are the same length and contain the same bytes.
// A nil argument is equivalent to an empty slice.
func Equal(a, b []byte) bool {
        // Neither cmd/compile nor gccgo allocates for these string conversions.
        return string(a) == string(b)
}

However, the []byte->string conversion does allocate on TinyGo. We should replace calls to bytes.Equal with a call to our own function that doesn't allocate.

dgryski avatar Dec 16 '23 18:12 dgryski

I'd like to avoid an optimization like that because it just seems a bit hacky to me. (We have a number of those optimizations in TinyGo, but generally they're to replace a call to a LLVM intrinsic). Instead, I'd propose we add a new transform just like our current OptimizeStringToBytes but the other way round.

Here is the transform:

https://github.com/tinygo-org/tinygo/blob/731532cd2b6353b60b443343b51296ec0fafae09/transform/rtcalls.go#L12-L18

The benefit of doing it like that is that it also fixes every other cast that looks like that, instead of just the bytes.Equal case.

aykevl avatar Dec 16 '23 19:12 aykevl

shouldn't that do something equivalent like memcmp?

kevyonan avatar Dec 17 '23 04:12 kevyonan

@assyrianic Yes. You can't just immediately defer to memcmp though because you need to check for nil slices, check the lengths, and dereference the data pointers.

dgryski avatar Dec 17 '23 04:12 dgryski

We should replace calls to bytes.Equal with a call to our own function that doesn't allocate.

Maybe you're right. I looked at #4289 but realized that optimization is a lot less trivial than the existing string-to-[]bytes optimization. I think it can be replaced with a call to runtime.stringEqual (using the len part of the byte slice for the string length).

@lpereira

aykevl avatar Jun 10 '24 10:06 aykevl

There are quite a bit of string(b) conversions in the standard library, too, that would benefit from #4289. I can add a transform that makes bytes.Equal() better by itself, but I'm not sure how beneficial it would be, to be honest.

lpereira avatar Jun 11 '24 17:06 lpereira