diff --git a/bench/bench.sh b/bench/bench.sh new file mode 100644 index 0000000..6aa1e24 --- /dev/null +++ b/bench/bench.sh @@ -0,0 +1,16 @@ +#!/bin/bash + +DIR=$(cd $(dirname $BASH_SOURCE); pwd) + +gotest() { + cpu=${3:-$(nproc)} + go test -bench "$1" -benchmem -benchtime 5s -cpu $cpu . \ + | tee "$2" +} + +( + cd $DIR + gotest BenchmarkFilter_Volumes filter-volumes.txt + gotest BenchmarkFilter_Compare filter-compare-8.txt + gotest BenchmarkFilter_Compare filter-compare-1.txt 1 +) diff --git a/bench/filter-compare-1.txt b/bench/filter-compare-1.txt new file mode 100644 index 0000000..96e1007 --- /dev/null +++ b/bench/filter-compare-1.txt @@ -0,0 +1,10 @@ +goos: linux +goarch: amd64 +pkg: github.com/meian/gcf/bench +cpu: Intel(R) Core(TM) i5-8250U CPU @ 1.60GHz +BenchmarkFilter_Compare/filter 2338778 2547 ns/op 144 B/op 4 allocs/op +BenchmarkFilter_Compare/if-func 9481165 620.8 ns/op 0 B/op 0 allocs/op +BenchmarkFilter_Compare/if-inline 155062731 38.53 ns/op 0 B/op 0 allocs/op +BenchmarkFilter_Compare/chan 76498 78090 ns/op 384 B/op 6 allocs/op +PASS +ok github.com/meian/gcf/bench 31.790s diff --git a/bench/filter-compare-8.txt b/bench/filter-compare-8.txt new file mode 100644 index 0000000..ae5dcbd --- /dev/null +++ b/bench/filter-compare-8.txt @@ -0,0 +1,10 @@ +goos: linux +goarch: amd64 +pkg: github.com/meian/gcf/bench +cpu: Intel(R) Core(TM) i5-8250U CPU @ 1.60GHz +BenchmarkFilter_Compare/filter-8 2325522 2551 ns/op 144 B/op 4 allocs/op +BenchmarkFilter_Compare/if-func-8 9611860 643.7 ns/op 0 B/op 0 allocs/op +BenchmarkFilter_Compare/if-inline-8 155326840 38.86 ns/op 0 B/op 0 allocs/op +BenchmarkFilter_Compare/chan-8 41066 151074 ns/op 384 B/op 6 allocs/op +PASS +ok github.com/meian/gcf/bench 33.025s diff --git a/bench/filter-volumes.txt b/bench/filter-volumes.txt new file mode 100644 index 0000000..6b2c266 --- /dev/null +++ b/bench/filter-volumes.txt @@ -0,0 +1,18 @@ +goos: linux +goarch: amd64 +pkg: github.com/meian/gcf/bench +cpu: Intel(R) Core(TM) i5-8250U CPU @ 1.60GHz +BenchmarkFilter_Volumes/slice=10/filter=1-8 28708957 200.3 ns/op 80 B/op 2 allocs/op +BenchmarkFilter_Volumes/slice=10/filter=5-8 8568411 694.7 ns/op 208 B/op 6 allocs/op +BenchmarkFilter_Volumes/slice=10/filter=10-8 4603394 1299 ns/op 368 B/op 11 allocs/op +BenchmarkFilter_Volumes/slice=10/filter=100-8 490940 11025 ns/op 3248 B/op 101 allocs/op +BenchmarkFilter_Volumes/slice=100/filter=1-8 5878351 1015 ns/op 80 B/op 2 allocs/op +BenchmarkFilter_Volumes/slice=100/filter=5-8 1290842 4663 ns/op 208 B/op 6 allocs/op +BenchmarkFilter_Volumes/slice=100/filter=10-8 698023 8287 ns/op 368 B/op 11 allocs/op +BenchmarkFilter_Volumes/slice=100/filter=100-8 87264 67737 ns/op 3248 B/op 101 allocs/op +BenchmarkFilter_Volumes/slice=1000/filter=1-8 598560 9192 ns/op 80 B/op 2 allocs/op +BenchmarkFilter_Volumes/slice=1000/filter=5-8 157719 44673 ns/op 208 B/op 6 allocs/op +BenchmarkFilter_Volumes/slice=1000/filter=10-8 81381 78245 ns/op 368 B/op 11 allocs/op +BenchmarkFilter_Volumes/slice=1000/filter=100-8 8083 636071 ns/op 3248 B/op 101 allocs/op +PASS +ok github.com/meian/gcf/bench 81.086s diff --git a/bench/filter_test.go b/bench/filter_test.go index bbe00ee..917f9c3 100644 --- a/bench/filter_test.go +++ b/bench/filter_test.go @@ -1,166 +1,150 @@ package gcf_test import ( + "fmt" "testing" "github.com/meian/gcf" ) -func BenchmarkFilter_100_1(b *testing.B) { - // usually case - benchFilter(b, 100, 1, func(i int) func(int) bool { - return func(v int) bool { - return v/100 > i +func BenchmarkFilter_Volumes(b *testing.B) { + sLens := []int{10, 100, 1000} + fLens := []int{1, 5, 10, 100} + for _, sLen := range sLens { + for _, fLen := range fLens { + name := fmt.Sprintf("slice=%d/filter=%d", sLen, fLen) + b.Run(name, func(b *testing.B) { + s := make([]int, sLen) + for i := range s { + s[i] = i + 1 + } + itb := gcf.FromSlice(s) + for i := 0; i < fLen; i++ { + itb = gcf.Filter(itb, func(v int) bool { + return true + }) + } + b.ResetTimer() + for i := 0; i < b.N; i++ { + it := itb.Iterator() + for it.MoveNext() { + } + } + }) } - }) -} - -func BenchmarkFilter_1000_10(b *testing.B) { - // usually large case - benchFilter(b, 1000, 10, func(i int) func(int) bool { - return func(v int) bool { - return v/100 > i - } - }) -} - -func BenchmarkFilter_100_100(b *testing.B) { - benchFilter(b, 100, 100, func(i int) func(int) bool { - return func(v int) bool { - return v > i - } - }) -} - -func BenchmarkFilter_200_100(b *testing.B) { - benchFilter(b, 200, 100, func(i int) func(int) bool { - return func(v int) bool { - return v/2 > i - } - }) -} - -func BenchmarkFilter_1000_100(b *testing.B) { - benchFilter(b, 1000, 100, func(i int) func(int) bool { - return func(v int) bool { - return v/10 > i - } - }) -} - -func BenchmarkFilter_100_200(b *testing.B) { - benchFilter(b, 100, 200, func(i int) func(int) bool { - return func(v int) bool { - return v*2 > i - } - }) -} - -func BenchmarkFilter_100_1000(b *testing.B) { - benchFilter(b, 100, 1000, func(i int) func(int) bool { - return func(v int) bool { - return v*10 > i - } - }) + } } -func benchFilter(b *testing.B, sLen, itCnt int, f func(int) func(int) bool) { - s := make([]int, sLen) - for i := range s { +func BenchmarkFilter_Compare(b *testing.B) { + s := make([]int, 100) + for i := 0; i < len(s); i++ { s[i] = i + 1 } - itb := gcf.FromSlice(s) - for i := 0; i < itCnt; i++ { - i := i - itb = gcf.Filter(itb, f(i)) + f13 := func(v int) bool { + return v%13 > 0 } - b.ResetTimer() - for i := 0; i < b.N; i++ { - sum := 0 - it := itb.Iterator() - for it.MoveNext() { - sum += it.Current() - } + f11 := func(v int) bool { + return v%11 > 0 + } + f7 := func(v int) bool { + return v%7 > 0 } -} - -func BenchmarkOnLoop_100_1(b *testing.B) { - benchOnLoop(b, 100, 1, func(v int) func(int) bool { - return func(i int) bool { - return v/100 > i - } - }) -} - -func BenchmarkOnLoop_1000_10(b *testing.B) { - benchOnLoop(b, 1000, 10, func(v int) func(int) bool { - return func(i int) bool { - return v/100 > i - } - }) -} - -func BenchmarkOnLoop_100_100(b *testing.B) { - benchOnLoop(b, 100, 100, func(v int) func(int) bool { - return func(i int) bool { - return v > i - } - }) -} - -func BenchmarkOnLoop_200_100(b *testing.B) { - benchOnLoop(b, 200, 100, func(v int) func(int) bool { - return func(i int) bool { - return v/2 > i - } - }) -} -func BenchmarkOnLoop_1000_100(b *testing.B) { - benchOnLoop(b, 1000, 100, func(v int) func(int) bool { - return func(i int) bool { - return v/10 > i + b.Run("filter", func(b *testing.B) { + s := append([]int{}, s...) + itb := gcf.FromSlice(s) + itb = gcf.Filter(itb, f13) + itb = gcf.Filter(itb, f11) + itb = gcf.Filter(itb, f7) + b.ResetTimer() + n := 0 + for i := 0; i < b.N; i++ { + n = 0 + it := itb.Iterator() + for it.MoveNext() { + n++ + } } }) -} -func BenchmarkOnLoop_100_200(b *testing.B) { - benchOnLoop(b, 100, 200, func(v int) func(int) bool { - return func(i int) bool { - return v*2 > i + b.Run("if-func", func(b *testing.B) { + s := append([]int{}, s...) + b.ResetTimer() + n := 0 + for i := 0; i < b.N; i++ { + n = 0 + for _, v := range s { + if !f13(v) { + continue + } + if !f11(v) { + continue + } + if !f7(v) { + continue + } + n++ + } } }) -} -func BenchmarkOnLoop_100_1000(b *testing.B) { - benchOnLoop(b, 100, 1000, func(v int) func(int) bool { - return func(i int) bool { - return v*10 > i + b.Run("if-inline", func(b *testing.B) { + s := append([]int{}, s...) + b.ResetTimer() + n := 0 + for i := 0; i < b.N; i++ { + n = 0 + for _, v := range s { + if v%13 == 0 { + continue + } + if v%11 == 0 { + continue + } + if v%7 == 0 { + continue + } + n++ + } } }) -} -func benchOnLoop(b *testing.B, sLen, lpCnt int, f func(int) func(int) bool) { - s := make([]int, sLen) - for i := range s { - s[i] = i + 1 - } - b.ResetTimer() - for i := 0; i < b.N; i++ { - sum := 0 - for _, v := range s { - if filterOnLoop(f(v), lpCnt) { - sum += v + b.Run("chan", func(b *testing.B) { + s := append([]int{}, s...) + b.ResetTimer() + n := 0 + for i := 0; i < b.N; i++ { + n = 0 + c13 := make(chan int) + c11 := make(chan int) + c7 := make(chan int) + go func() { + defer close(c13) + for _, v := range s { + if v%13 > 0 { + c13 <- v + } + } + }() + go func() { + defer close(c11) + for v := range c13 { + if v%11 > 0 { + c11 <- v + } + } + }() + go func() { + defer close(c7) + for v := range c11 { + if v%7 > 0 { + c7 <- v + } + } + }() + for range c7 { + n++ } } - } -} - -func filterOnLoop(f func(int) bool, n int) bool { - for i := 0; i < n; i++ { - if !f(i) { - return false - } - } - return true + }) }