Pattern:
func process(inputs []string) {
// (1)
c := make(chan string, len(inputs))
for _, x := range inputs {
c<-x
}
close(c)
// (2) spin up go routine, do some work.
// (3) wait for results, error.
}
Let's see how we can make (1) more efficient.
ReadOnlyChanFromSlice
: safe, this code above.ReadOnlyChanFromSliceUnsafe
: unsafe, copy the input directly to the chan's buffer.BenchmarkUnsafer
: unsafer, makes the chan point to the input directly.
(go 1.16.6)
Please don't do this.
goos: linux
goarch: amd64
pkg: github.com/pelletier/foo
cpu: AMD Ryzen 9 5950X 16-Core Processor
BenchmarkSafe/strings_1-32 13653536 87.90 ns/op 112 B/op 2 allocs/op
BenchmarkSafe/strings_3-32 8785500 181.0 ns/op 144 B/op 2 allocs/op
BenchmarkSafe/strings_32-32 1892090 635.6 ns/op 608 B/op 2 allocs/op
BenchmarkSafe/strings_100-32 667189 1805 ns/op 1888 B/op 2 allocs/op
BenchmarkSafe/strings_1000-32 71019 16853 ns/op 16480 B/op 2 allocs/op
BenchmarkSafe/strings_10000-32 6999 169562 ns/op 163936 B/op 2 allocs/op
BenchmarkUnsafe/strings_1-32 14865825 80.16 ns/op 112 B/op 2 allocs/op
BenchmarkUnsafe/strings_3-32 12097567 98.35 ns/op 144 B/op 2 allocs/op
BenchmarkUnsafe/strings_32-32 5981284 200.5 ns/op 608 B/op 2 allocs/op
BenchmarkUnsafe/strings_100-32 2817764 429.3 ns/op 1888 B/op 2 allocs/op
BenchmarkUnsafe/strings_1000-32 409248 2975 ns/op 16480 B/op 2 allocs/op
BenchmarkUnsafe/strings_10000-32 27013 46426 ns/op 163936 B/op 2 allocs/op
BenchmarkUnsafer/strings_1-32 30140151 40.36 ns/op 96 B/op 1 allocs/op
BenchmarkUnsafer/strings_3-32 31440512 40.51 ns/op 96 B/op 1 allocs/op
BenchmarkUnsafer/strings_32-32 30768156 39.77 ns/op 96 B/op 1 allocs/op
BenchmarkUnsafer/strings_100-32 27903132 40.11 ns/op 96 B/op 1 allocs/op
BenchmarkUnsafer/strings_1000-32 29842083 39.70 ns/op 96 B/op 1 allocs/op
BenchmarkUnsafer/strings_10000-32 28547709 40.79 ns/op 96 B/op 1 allocs/op
PASS