-
Notifications
You must be signed in to change notification settings - Fork 18.5k
Description
What version of Go are you using (go version)?
playground (1.21, i think?)
Does this issue reproduce with the latest release?
presumably
What operating system and processor architecture are you using (go env)?
N/A, should happen everywhere
What did you do?
https://go.dev/play/p/CcJuPywA867
summary: nest a handful of objects each of which is a struct{a, b, c, d any}, so that each points four times to the next. compare the "top" one. at N=16 or so, this begins taking longer to compare than the playground will let it run.
What did you expect to see?
I don't know.
What did you see instead?
Timeouts.
On the one hand, this is clearly You're Holding It Wrong. Don't Do That Then. Etcetera.
But I think in nearly all cases, I've been well-served by my belief that comparing go objects would have reasonably bounded runtime, because after all, anything that would cause them to explode or whatever would end up with pointer comparisons, and pointer comparisons come out equal-or-unequal quickly and easily. But interfaces provide a way to have a thing which sort of partakes in pointer-ish semantics, but doesn't actually fully copy things. If you weren't using interfaces for this, you'd actually have to populate all 4^16 items, or you'd have to use pointers (and then the comparisons would be fast). Interfaces let us bypass that perfectly good intuition and have copies of an arbitrarily-large nested tree that don't actually require copying it, but also don't enjoy the "we can compare these quickly" behavior of pointers. So each tier of this structure copies the next tier's four-interfaces header, but doesn't dereference the next tier's objects, so you can assemble the structure in time that's pretty much just linear with tree depth, but reading it is exponential.
On the one hand, I don't see a way to exploit this through user input to, say, encoding/json or anything like that. On the other hand, it feels like the way in which interface types are allowing us to, by copying a few words, create a thing that will act like it contains megabytes of data when you do == on it, is... unusual? Distinctive?
Obviously this is extremely susceptible to a small cache. On the other hand, the expense of building that cache for most comparisons would be punitive to every other go program in the world, pretty much. I don't have a good idea how to address this, or even whether it's worth addressing, but it sure is weird.