Closed vladislav-valkov-omniverse closed 6 months ago
@vladislav-valkov-omniverse - what you are likely noticing is that variadic functions need to allocate a slice (behind the scenes) to accomplish handling all the arguments.
Now I could be wrong but I think that’s why and I don’t yet know a way around this.
Having a ContainsOne could help for checking a single item…but first I’d like to figure out if such a method is necessary.
Also, just to be pragmatic heap allocations aren’t the end of the world if the code isn’t in some hotspot.
@deckarep I usually see variadic parameters being marked as non-escaped - as all slices under certain size should be. I have found only one way to make such value be allocated on heap yet - variadic argument of generic type inside an interface. When I call the same method of a struct (or just replace the generic with a concrete type), everything works fine. Perhaps I should try searching for similar issues in Go repository.
In general, I agree heap allocations are not a disaster, but my specific usecase has a lot of checks involving sets, and this discovery was quite frustrating.
@vladislav-valkov-omniverse - I understand the concern which I suppose would be an issue where you are checking for elements in a hot part of the code with the Contains
method. I do agree with you that it would be nice to not see any allocs for this.
We can move forward with a ContainsOne
addition to the API if you'd like to contribute the changes.
Just to be clear however, if you are having lots of contention with heap escaped data and you need finer grain control you might want to consider using a language which gives you such fine grained control such as Rust or Zig.
In Go, I prefer to have a clean and simple API that works in most general cases versus trying to squeeze out the absolute most performant package ever which is not a goal of this project.
That said, this project has landed dozens of great and impactful optimizations where it makes sense to do so while keeping a healthy and balanced API design.
ContainsOne has been added to Release: 2.6.0
I have noticed
Contains()
method leads its parameters to be allocated on the heap.Building the code above with
go run -gcflags="-m" main.go
shows that Contains() parameter escapes to heap:./main.go:7:12: ... argument escapes to heap
I forked the library and ran several benchmarks:
And got the following results:
I tried adding a new method which does not use variadic parameter:
and got the following result for the new benchmark: