Thesis

The accepted paradigm for doing set contains (or set operations in general) pre Go 1.18 (generics) is to use a map[type]struct{}. I believe that using this for small datasets is going to be slower than using slices. I also just don't like the way map[string]struct{}{} looks. Disgusting.

String Results

Summary

Slices only behaved better on small N, and only slightly. When we were at N = 100, we already are at a 30% faster using MapSet. Looks like for most string cases, using a map as the underlying storage makes sense.

N = 100

BenchmarkSliceSet-10       	   51308	     22884 ns/op
BenchmarkSliceSetExp-10    	   54638	     22027 ns/op
BenchmarkMapSet-10         	   79706	     14912 ns/op

N = 1000

BenchmarkSliceSet-10       	     741	   1504577 ns/op
BenchmarkSliceSetExp-10    	     793	   1535511 ns/op
BenchmarkMapSet-10         	    6694	    180629 ns/op

N = 10

BenchmarkSliceSet-10       	 1110586	      1066 ns/op
BenchmarkSliceSetExp-10    	 1000000	      1052 ns/op
BenchmarkMapSet-10         	  987474	      1222 ns/op

Int results

Summary

Ints perform better as slices for longer. At N = 100, we still have it at about 54% faster. However, the gap really widens once we get to N = 1000.

N = 100

BenchmarkIntMapSet-10      	  197214	      5917 ns/op
BenchmarkIntSliceSet-10    	  435561	      2709 ns/op

N = 10

BenchmarkIntMapSet-10      	 3872775	       311.5 ns/op
BenchmarkIntSliceSet-10    	 8202166	       144.7 ns/op

N = 1000

BenchmarkIntMapSet-10      	   20090	     60114 ns/op
BenchmarkIntSliceSet-10    	    6854	    175596 ns/op