-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
improve sliceutil.RemoveMatch, additional tests for ctxutil & traceutil
- Loading branch information
Showing
6 changed files
with
327 additions
and
13 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
package ctxutil | ||
|
||
import ( | ||
"sync" | ||
"testing" | ||
|
||
"github.com/stretchr/testify/require" | ||
|
||
"github.com/eluv-io/common-go/util/traceutil/trace" | ||
) | ||
|
||
func TestCleanup(t *testing.T) { | ||
// make sure cleanup works with wrapped spans | ||
root := newLogSpan(Current().InitTracing("root")) | ||
|
||
wg := sync.WaitGroup{} | ||
for i := 0; i < 100; i++ { | ||
wg.Add(1) | ||
ctx := Current().Ctx() | ||
go func() { | ||
defer Current().Push(ctx)() | ||
span := Current().StartSpan("s1") | ||
span.Attribute("attr", "blub") | ||
|
||
span2 := Current().StartSpan("s2") | ||
span2.End() | ||
|
||
span.End() | ||
wg.Done() | ||
}() | ||
} | ||
|
||
wg.Wait() | ||
|
||
root.End() | ||
require.Empty(t, Current().(*contextStack).stacks) | ||
|
||
root.Log() | ||
} | ||
|
||
func newLogSpan(span trace.Span) *logSpan { | ||
return &logSpan{ | ||
Span: span, | ||
} | ||
} | ||
|
||
type logSpan struct { | ||
trace.Span | ||
once sync.Once | ||
} | ||
|
||
func (s *logSpan) Log() { | ||
s.once.Do(func() { | ||
log.Info("collected trace", "trace", s.Span.Json()) | ||
// would be more efficient if logging disabled: | ||
// log.Info("collected trace", "trace", jsonutil.Stringer(s.Span)) | ||
}) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
package sliceutil_test | ||
|
||
import ( | ||
"fmt" | ||
"testing" | ||
|
||
"github.com/stretchr/testify/require" | ||
|
||
"github.com/eluv-io/common-go/util/sliceutil" | ||
) | ||
|
||
// baseline current version: | ||
// | ||
// goos: darwin | ||
// goarch: amd64 | ||
// pkg: github.com/eluv-io/common-go/util/sliceutil | ||
// cpu: Intel(R) Core(TM) i9-9980HK CPU @ 2.40GHz | ||
// BenchmarkRemoveMatch | ||
// BenchmarkRemoveMatch/slice_len_10 | ||
// BenchmarkRemoveMatch/slice_len_10-16 487131 2367 ns/op | ||
// BenchmarkRemoveMatch/slice_len_100 | ||
// BenchmarkRemoveMatch/slice_len_100-16 387724 2637 ns/op | ||
// BenchmarkRemoveMatch/slice_len_1000 | ||
// BenchmarkRemoveMatch/slice_len_1000-16 232868 5655 ns/op | ||
// BenchmarkRemoveMatch/slice_len_10000 | ||
// BenchmarkRemoveMatch/slice_len_10000-16 40525 30455 ns/op | ||
// BenchmarkRemoveMatch/slice_len_100000 | ||
// BenchmarkRemoveMatch/slice_len_100000-16 4180 307099 ns/op | ||
// PASS | ||
// | ||
// original version: | ||
// | ||
// goos: darwin | ||
// goarch: amd64 | ||
// pkg: github.com/eluv-io/common-go/util/sliceutil | ||
// cpu: Intel(R) Core(TM) i9-9980HK CPU @ 2.40GHz | ||
// BenchmarkRemoveMatch | ||
// BenchmarkRemoveMatch/slice_len_10 | ||
// BenchmarkRemoveMatch/slice_len_10-16 491574 2329 ns/op | ||
// BenchmarkRemoveMatch/slice_len_100 | ||
// BenchmarkRemoveMatch/slice_len_100-16 381914 3376 ns/op | ||
// BenchmarkRemoveMatch/slice_len_1000 | ||
// BenchmarkRemoveMatch/slice_len_1000-16 37308 29885 ns/op | ||
// BenchmarkRemoveMatch/slice_len_10000 | ||
// BenchmarkRemoveMatch/slice_len_10000-16 312 3780946 ns/op | ||
// BenchmarkRemoveMatch/slice_len_100000 | ||
// BenchmarkRemoveMatch/slice_len_100000-16 2 611002579 ns/op | ||
// PASS | ||
func BenchmarkRemoveMatch(b *testing.B) { | ||
sliceLens := []int{10, 100, 1000, 10000, 100_000} | ||
for _, sliceLen := range sliceLens { | ||
b.Run(fmt.Sprintf("slice len %d", sliceLen), func(b *testing.B) { | ||
for i := 0; i < b.N; i++ { | ||
b.StopTimer() | ||
slice := generateSlice(sliceLen) | ||
b.StartTimer() | ||
res, removed := sliceutil.RemoveMatch(slice, func(e int) bool { | ||
return e >= 5 | ||
}) | ||
require.Equal(b, sliceLen/2, len(res)) | ||
require.Equal(b, sliceLen/2, removed) | ||
} | ||
}) | ||
} | ||
} | ||
|
||
func generateSlice(len int) []int { | ||
slice := make([]int, len) | ||
for i, _ := range slice { | ||
slice[i] = i % 10 | ||
} | ||
return slice | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
package sliceutil_test | ||
|
||
import ( | ||
"fmt" | ||
|
||
"github.com/eluv-io/common-go/util/sliceutil" | ||
) | ||
|
||
func ExampleRemoveMatch() { | ||
slice := []int{1, 2, 3, 1, 2, 3, 6, 6, 4, 2, 4} | ||
res, i := sliceutil.RemoveMatch(slice, func(e int) bool { | ||
return e >= 3 | ||
}) | ||
fmt.Printf("removed %d elements: %v\n", i, res) | ||
fmt.Printf("removed slots in original slice are zeroed: %v\n", slice) | ||
|
||
// Output: | ||
// | ||
// removed 6 elements: [1 2 1 2 2] | ||
// removed slots in original slice are zeroed: [1 2 1 2 2 0 0 0 0 0 0] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,146 @@ | ||
package traceutil_test | ||
|
||
import ( | ||
"fmt" | ||
"sync" | ||
"time" | ||
|
||
"github.com/eluv-io/common-go/format/duration" | ||
"github.com/eluv-io/common-go/util/ctxutil" | ||
"github.com/eluv-io/common-go/util/jsonutil" | ||
"github.com/eluv-io/common-go/util/traceutil" | ||
"github.com/eluv-io/common-go/util/traceutil/trace" | ||
) | ||
|
||
func A() { | ||
span := traceutil.StartSpan("func A") | ||
time.Sleep(time.Second) | ||
defer span.End() | ||
} | ||
|
||
func B() { | ||
span := traceutil.StartSpan("func B") | ||
time.Sleep(500 * time.Millisecond) | ||
defer span.End() | ||
} | ||
|
||
func Sequential() { | ||
span := traceutil.StartSpan("calling A() and B() sequentially") | ||
defer span.End() | ||
A() | ||
B() | ||
} | ||
|
||
func Parallel() { | ||
span := traceutil.StartSpan("calling A() and B() concurrently") | ||
defer span.End() | ||
|
||
wg := sync.WaitGroup{} | ||
wg.Add(2) | ||
|
||
ctx := ctxutil.Ctx() | ||
go func() { | ||
defer ctxutil.Current().Push(ctx)() | ||
A() | ||
wg.Done() | ||
}() | ||
time.Sleep(50 * time.Millisecond) | ||
go func() { | ||
defer ctxutil.Current().Push(ctx)() | ||
B() | ||
wg.Done() | ||
}() | ||
|
||
wg.Wait() | ||
} | ||
|
||
func Parallel2() { | ||
span := traceutil.StartSpan("calling A() and B() concurrently") | ||
defer span.End() | ||
|
||
wg := sync.WaitGroup{} | ||
wg.Add(2) | ||
|
||
ctxutil.Current().Go(func() { | ||
A() | ||
wg.Done() | ||
}) | ||
time.Sleep(50 * time.Millisecond) | ||
ctxutil.Current().Go(func() { | ||
B() | ||
wg.Done() | ||
}) | ||
|
||
wg.Wait() | ||
} | ||
|
||
func ExampleMultiGoRoutine() { | ||
rootSpan := traceutil.InitTracing("root span") | ||
|
||
Sequential() | ||
Parallel() | ||
Parallel2() | ||
|
||
rootSpan.End() | ||
|
||
// truncate span durations to have reproducible output | ||
spans := []trace.Span{rootSpan.FindByName("root span")} | ||
for len(spans) > 0 { | ||
span := spans[len(spans)-1].(*trace.RecordingSpan) | ||
span.Data.Duration = duration.Spec(span.Data.Duration.Duration().Truncate(500 * time.Millisecond)) | ||
spans = append(spans[:len(spans)-1], span.Data.Subs...) | ||
} | ||
fmt.Println(jsonutil.MustPretty(rootSpan.Json())) | ||
|
||
// Output: | ||
// | ||
// { | ||
// "name": "root span", | ||
// "time": "3.5s", | ||
// "subs": [ | ||
// { | ||
// "name": "calling A() and B() sequentially", | ||
// "time": "1.5s", | ||
// "subs": [ | ||
// { | ||
// "name": "func A", | ||
// "time": "1s" | ||
// }, | ||
// { | ||
// "name": "func B", | ||
// "time": "500ms" | ||
// } | ||
// ] | ||
// }, | ||
// { | ||
// "name": "calling A() and B() concurrently", | ||
// "time": "1s", | ||
// "subs": [ | ||
// { | ||
// "name": "func A", | ||
// "time": "1s" | ||
// }, | ||
// { | ||
// "name": "func B", | ||
// "time": "500ms" | ||
// } | ||
// ] | ||
// }, | ||
// { | ||
// "name": "calling A() and B() concurrently", | ||
// "time": "1s", | ||
// "subs": [ | ||
// { | ||
// "name": "func A", | ||
// "time": "1s" | ||
// }, | ||
// { | ||
// "name": "func B", | ||
// "time": "500ms" | ||
// } | ||
// ] | ||
// } | ||
// ] | ||
// } | ||
|
||
} |