Skip to content

[Question] Contains() parameters escape to heap #118

Closed
@vladislav-valkov-omniverse

Description

I have noticed Contains() method leads its parameters to be allocated on the heap.

package main

import mapset "github.com/deckarep/golang-set/v2"

func main() {
	a := mapset.NewSet[int]()
	a.Contains(1)
}

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:

func BenchmarkContainsSlice(b *testing.B) {
	slice := make([]int, 10000)
	for i := 0; i < 10000; i++ {
		slice[i] = i
	}

	set := mapset.NewThreadUnsafeSet[int](slice...)
	for i := 0; i < b.N; i++ {
		set.Contains(slice...)
	}
}

func BenchmarkContainsVariadic(b *testing.B) {
	slice := make([]int, 10000)
	for i := 0; i < 10000; i++ {
		slice[i] = i
	}

	set := mapset.NewThreadUnsafeSet[int](slice...)
	for i := 0; i < b.N; i++ {
		for i := 0; i < len(slice); i++ {
			set.Contains(i)
		}
	}
}

And got the following results:

goos: darwin
goarch: arm64
pkg: variadic-escaping-test
BenchmarkContainsSlice
BenchmarkContainsSlice-10          	    6258	    176586 ns/op	      42 B/op	       0 allocs/op
BenchmarkContainsVariadic
BenchmarkContainsVariadic-10       	    4209	    277876 ns/op	   80063 B/op	   10000 allocs/op

I tried adding a new method which does not use variadic parameter:

type Set[T comparable] interface {
	ContainsOne(val T) bool
}

func BenchmarkContainsNonVariadic(b *testing.B) {
	slice := make([]int, 10000)
	for i := 0; i < 10000; i++ {
		slice[i] = i
	}

	a := mapset.NewThreadUnsafeSet[int](slice...)
	for i := 0; i < b.N; i++ {
		for i := 0; i < len(slice); i++ {
			a.ContainsOne(i)
		}
	}
}

and got the following result for the new benchmark:

BenchmarkContainsNonVariadic
BenchmarkContainsNonVariadic-10    	    6762	    170547 ns/op	      39 B/op	       0 allocs/op
  • Is there a known fix for this problem?
  • Should I open a PR to add the new method?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions