diff --git a/hack/tools/metrics/main.go b/hack/tools/metrics/main.go index e25c167ada..c2d1bad960 100644 --- a/hack/tools/metrics/main.go +++ b/hack/tools/metrics/main.go @@ -14,17 +14,18 @@ package main import ( + "cmp" "encoding/gob" "flag" "fmt" "image/color" "io/fs" "os" + "slices" "github.com/lucasb-eyer/go-colorful" "github.com/vdaas/vald/hack/benchmark/metrics" "github.com/vdaas/vald/internal/log" - "github.com/vdaas/vald/internal/slices" "gonum.org/v1/plot" "gonum.org/v1/plot/plotter" "gonum.org/v1/plot/vg" @@ -87,8 +88,8 @@ func run() error { step = 1 / float64(len(ms)-1) } for i, m := range ms { - slices.SortFunc(m.Search, func(left, right *metrics.SearchMetrics) bool { - return left.Recall < right.Recall + slices.SortFunc(m.Search, func(left, right *metrics.SearchMetrics) int { + return cmp.Compare(left.Recall, right.Recall) }) xys := make(plotter.XYs, len(m.Search)) for i, s := range m.Search { diff --git a/internal/file/file.go b/internal/file/file.go index 1f565a62cc..deee2ad8f7 100644 --- a/internal/file/file.go +++ b/internal/file/file.go @@ -18,10 +18,12 @@ package file import ( + "cmp" "context" "io/fs" "os" "path/filepath" + "slices" "strconv" "time" @@ -30,7 +32,6 @@ import ( "github.com/vdaas/vald/internal/io" "github.com/vdaas/vald/internal/log" "github.com/vdaas/vald/internal/safety" - "github.com/vdaas/vald/internal/slices" "github.com/vdaas/vald/internal/strings" "github.com/vdaas/vald/internal/sync/errgroup" ) @@ -338,7 +339,7 @@ func ReadDir(path string) (dirs []fs.DirEntry, err error) { }() dirs, err = f.ReadDir(-1) - slices.SortFunc(dirs, func(a, b fs.DirEntry) bool { return a.Name() < b.Name() }) + slices.SortFunc(dirs, func(a, b fs.DirEntry) int { return cmp.Compare(a.Name(), b.Name()) }) return dirs, err } diff --git a/internal/info/info.go b/internal/info/info.go index b948ac8905..c375145f50 100644 --- a/internal/info/info.go +++ b/internal/info/info.go @@ -21,11 +21,11 @@ import ( "fmt" "reflect" "runtime" + "slices" "strconv" "github.com/vdaas/vald/internal/errors" "github.com/vdaas/vald/internal/log" - "github.com/vdaas/vald/internal/slices" "github.com/vdaas/vald/internal/strings" "github.com/vdaas/vald/internal/sync" ) diff --git a/internal/net/grpc/pool/pool.go b/internal/net/grpc/pool/pool.go index 6be2b9373b..8f195bc2c1 100644 --- a/internal/net/grpc/pool/pool.go +++ b/internal/net/grpc/pool/pool.go @@ -21,6 +21,7 @@ import ( "context" "fmt" "math" + "slices" "strconv" "sync/atomic" "time" @@ -30,7 +31,6 @@ import ( "github.com/vdaas/vald/internal/log" "github.com/vdaas/vald/internal/net" "github.com/vdaas/vald/internal/safety" - "github.com/vdaas/vald/internal/slices" "github.com/vdaas/vald/internal/strings" "github.com/vdaas/vald/internal/sync" "github.com/vdaas/vald/internal/sync/errgroup" diff --git a/internal/net/grpc/stream.go b/internal/net/grpc/stream.go index 0efa399293..eac59c976c 100644 --- a/internal/net/grpc/stream.go +++ b/internal/net/grpc/stream.go @@ -18,6 +18,7 @@ package grpc import ( + "cmp" "context" "fmt" "runtime" @@ -74,8 +75,8 @@ func BidirectionalStream[Q any, R any](ctx context.Context, stream ServerStream, errs = append(errs, err) emu.Unlock() } - slices.RemoveDuplicates(errs, func(left, right error) bool { - return left.Error() < right.Error() + slices.RemoveDuplicates(errs, func(left, right error) int { + return cmp.Compare(left.Error(), right.Error()) }) emu.Lock() err = errors.Join(errs...) diff --git a/internal/slices/slices.go b/internal/slices/slices.go index 82e87e0731..05e5ec757c 100644 --- a/internal/slices/slices.go +++ b/internal/slices/slices.go @@ -14,27 +14,14 @@ package slices import ( - "golang.org/x/exp/constraints" - "golang.org/x/exp/slices" + "slices" ) -func Sort[E constraints.Ordered](x []E) { - slices.Sort(x) -} - -func SortFunc[E any](x []E, less func(left, right E) bool) { - slices.SortFunc(x, less) -} - -func SortStableFunc[E any](x []E, less func(left, right E) bool) { - slices.SortStableFunc(x, less) -} - -func RemoveDuplicates[E comparable](x []E, less func(left, right E) bool) []E { +func RemoveDuplicates[E comparable](x []E, less func(left, right E) int) []E { if len(x) < 2 { return x } - SortStableFunc(x, less) + slices.SortStableFunc(x, less) up := 0 // uniqPointer for i := 1; i < len(x); i++ { if x[up] != x[i] { diff --git a/internal/slices/slices_test.go b/internal/slices/slices_test.go index 9791cc341f..93adc795bc 100644 --- a/internal/slices/slices_test.go +++ b/internal/slices/slices_test.go @@ -21,266 +21,10 @@ import ( "github.com/vdaas/vald/internal/test/goleak" ) -func TestSort(t *testing.T) { - type args struct { - x []int - } - type want struct { - want []int - } - type test struct { - name string - args args - want want - checkFunc func([]int, want) error - beforeFunc func(*testing.T, args) - afterFunc func(*testing.T, args) - } - defaultCheckFunc := func(got []int, w want) error { - if len(got) != len(w.want) { - return errors.New("len not match") - } - for i := 0; i < len(got); i++ { - if got[i] != w.want[i] { - return errors.New("slice not sorted") - } - } - return nil - } - tests := []test{ - { - name: "success to sort 10 elements", - args: args{ - x: []int{9, 8, 7, 6, 5, 4, 3, 2, 1, 0}, - }, - want: want{ - want: []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}, - }, - }, - { - name: "success to sort 1 elements", - args: args{ - x: []int{0}, - }, - want: want{ - want: []int{0}, - }, - }, - { - name: "success to sort 0 elements", - args: args{ - x: []int{}, - }, - want: want{ - want: []int{}, - }, - }, - } - - for _, tc := range tests { - test := tc - t.Run(test.name, func(tt *testing.T) { - tt.Parallel() - defer goleak.VerifyNone(tt, goleak.IgnoreCurrent()) - if test.beforeFunc != nil { - test.beforeFunc(tt, test.args) - } - if test.afterFunc != nil { - defer test.afterFunc(tt, test.args) - } - checkFunc := test.checkFunc - if test.checkFunc == nil { - checkFunc = defaultCheckFunc - } - - Sort(test.args.x) - if err := checkFunc(test.args.x, test.want); err != nil { - tt.Errorf("error = %v", err) - } - }) - } -} - -func TestSortFunc(t *testing.T) { - type args struct { - x []int - less func(left, right int) bool - } - type want struct { - want []int - } - type test struct { - name string - args args - want want - checkFunc func([]int, want) error - beforeFunc func(*testing.T, args) - afterFunc func(*testing.T, args) - } - - defaultLessFn := func(l, r int) bool { - return l < r - } - defaultCheckFunc := func(got []int, w want) error { - if len(got) != len(w.want) { - return errors.New("len not match") - } - for i := 0; i < len(got); i++ { - if got[i] != w.want[i] { - return errors.New("slice not sorted") - } - } - return nil - } - tests := []test{ - { - name: "success to sort 10 elements", - args: args{ - x: []int{9, 8, 7, 6, 5, 4, 3, 2, 1, 0}, - less: defaultLessFn, - }, - want: want{ - want: []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}, - }, - }, - { - name: "success to sort 1 elements", - args: args{ - x: []int{0}, - less: defaultLessFn, - }, - want: want{ - want: []int{0}, - }, - }, - { - name: "success to sort 0 elements", - args: args{ - x: []int{}, - less: defaultLessFn, - }, - want: want{ - want: []int{}, - }, - }, - } - - for _, tc := range tests { - test := tc - t.Run(test.name, func(tt *testing.T) { - tt.Parallel() - defer goleak.VerifyNone(tt, goleak.IgnoreCurrent()) - if test.beforeFunc != nil { - test.beforeFunc(tt, test.args) - } - if test.afterFunc != nil { - defer test.afterFunc(tt, test.args) - } - checkFunc := test.checkFunc - if test.checkFunc == nil { - checkFunc = defaultCheckFunc - } - - SortFunc(test.args.x, test.args.less) - if err := checkFunc(test.args.x, test.want); err != nil { - tt.Errorf("error = %v", err) - } - }) - } -} - -func TestSortStableFunc(t *testing.T) { - type args struct { - x []int - less func(left, right int) bool - } - type want struct { - want []int - } - type test struct { - name string - args args - want want - checkFunc func([]int, want) error - beforeFunc func(*testing.T, args) - afterFunc func(*testing.T, args) - } - - defaultLessFn := func(l, r int) bool { - return l < r - } - defaultCheckFunc := func(got []int, w want) error { - if len(got) != len(w.want) { - return errors.New("len not match") - } - for i := 0; i < len(got); i++ { - if got[i] != w.want[i] { - return errors.New("slice not sorted") - } - } - return nil - } - tests := []test{ - { - name: "success to sort 10 elements", - args: args{ - x: []int{9, 8, 7, 6, 5, 4, 3, 2, 1, 0}, - less: defaultLessFn, - }, - want: want{ - want: []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}, - }, - }, - { - name: "success to sort 1 elements", - args: args{ - x: []int{0}, - less: defaultLessFn, - }, - want: want{ - want: []int{0}, - }, - }, - { - name: "success to sort 0 elements", - args: args{ - x: []int{}, - less: defaultLessFn, - }, - want: want{ - want: []int{}, - }, - }, - } - - for _, tc := range tests { - test := tc - t.Run(test.name, func(tt *testing.T) { - tt.Parallel() - defer goleak.VerifyNone(tt, goleak.IgnoreCurrent()) - if test.beforeFunc != nil { - test.beforeFunc(tt, test.args) - } - if test.afterFunc != nil { - defer test.afterFunc(tt, test.args) - } - checkFunc := test.checkFunc - if test.checkFunc == nil { - checkFunc = defaultCheckFunc - } - - SortStableFunc(test.args.x, test.args.less) - if err := checkFunc(test.args.x, test.want); err != nil { - tt.Errorf("error = %v", err) - } - }) - } -} - func TestRemoveDuplicates(t *testing.T) { type args struct { x []int - less func(left, right int) bool + less func(left, right int) int } type want struct { want []int diff --git a/pkg/agent/core/ngt/service/ngt.go b/pkg/agent/core/ngt/service/ngt.go index 1e1a75d291..3b598ceb7e 100644 --- a/pkg/agent/core/ngt/service/ngt.go +++ b/pkg/agent/core/ngt/service/ngt.go @@ -27,6 +27,7 @@ import ( "path/filepath" "reflect" "runtime" + "slices" "sync/atomic" "time" @@ -39,7 +40,6 @@ import ( "github.com/vdaas/vald/internal/log" "github.com/vdaas/vald/internal/observability/trace" "github.com/vdaas/vald/internal/safety" - "github.com/vdaas/vald/internal/slices" "github.com/vdaas/vald/internal/strings" "github.com/vdaas/vald/internal/sync" "github.com/vdaas/vald/internal/sync/errgroup" diff --git a/pkg/agent/core/ngt/service/vqueue/queue.go b/pkg/agent/core/ngt/service/vqueue/queue.go index 5d97511f6c..821d77ce35 100644 --- a/pkg/agent/core/ngt/service/vqueue/queue.go +++ b/pkg/agent/core/ngt/service/vqueue/queue.go @@ -18,14 +18,15 @@ package vqueue import ( + "cmp" "context" "reflect" + "slices" "sync/atomic" "time" "github.com/vdaas/vald/internal/errors" "github.com/vdaas/vald/internal/log" - "github.com/vdaas/vald/internal/slices" "github.com/vdaas/vald/internal/sync" ) @@ -197,9 +198,8 @@ func (v *vqueue) RangePopInsert(ctx context.Context, now int64, f func(uuid stri } return true }) - slices.SortFunc(uii, func(left, right index) bool { - // sort by latest unix time order - return left.date > right.date + slices.SortFunc(uii, func(left, right index) int { + return cmp.Compare(right.date, left.date) }) for _, idx := range uii { if !f(idx.uuid, idx.vector, idx.date) { @@ -232,9 +232,8 @@ func (v *vqueue) RangePopDelete(ctx context.Context, now int64, f func(uuid stri } return true }) - slices.SortFunc(udi, func(left, right index) bool { - // sort by latest unix time order - return left.date > right.date + slices.SortFunc(udi, func(left, right index) int { + return cmp.Compare(right.date, left.date) }) for _, idx := range udi { if !f(idx.uuid) { diff --git a/pkg/discoverer/k8s/service/discover.go b/pkg/discoverer/k8s/service/discover.go index 3a7d04ed6f..9a2773c431 100644 --- a/pkg/discoverer/k8s/service/discover.go +++ b/pkg/discoverer/k8s/service/discover.go @@ -18,8 +18,10 @@ package service import ( + "cmp" "context" "reflect" + "slices" "sync/atomic" "time" @@ -34,7 +36,6 @@ import ( "github.com/vdaas/vald/internal/log" "github.com/vdaas/vald/internal/net" "github.com/vdaas/vald/internal/safety" - "github.com/vdaas/vald/internal/slices" "github.com/vdaas/vald/internal/sync" "github.com/vdaas/vald/internal/sync/errgroup" ) @@ -303,8 +304,8 @@ func (d *discoverer) Start(ctx context.Context) (<-chan error, error) { for nodeName := range podsByNode { for namespace := range podsByNode[nodeName] { for appName, p := range podsByNode[nodeName][namespace] { - slices.SortFunc(p, func(left, right *payload.Info_Pod) bool { - return left.GetMemory().GetUsage() < right.GetMemory().GetUsage() + slices.SortFunc(p, func(left, right *payload.Info_Pod) int { + return cmp.Compare(left.GetMemory().GetUsage(), right.GetMemory().GetUsage()) }) podsByNode[nodeName][namespace][appName] = p nn, ok := nodeByName[nodeName] @@ -330,8 +331,8 @@ func (d *discoverer) Start(ctx context.Context) (<-chan error, error) { nn, ok := nodeByName[nodeName] if ok && nn.GetPods() != nil && nn.GetPods().GetPods() != nil { p := nn.GetPods().Pods - slices.SortFunc(p, func(left, right *payload.Info_Pod) bool { - return left.GetMemory().GetUsage() < right.GetMemory().GetUsage() + slices.SortFunc(p, func(left, right *payload.Info_Pod) int { + return cmp.Compare(left.GetMemory().GetUsage(), right.GetMemory().GetUsage()) }) nodeByName[nodeName].GetPods().Pods = p } @@ -345,8 +346,8 @@ func (d *discoverer) Start(ctx context.Context) (<-chan error, error) { defer wg.Done() for namespace := range podsByNamespace { for appName, p := range podsByNamespace[namespace] { - slices.SortFunc(p, func(left, right *payload.Info_Pod) bool { - return left.GetMemory().GetUsage() < right.GetMemory().GetUsage() + slices.SortFunc(p, func(left, right *payload.Info_Pod) int { + return cmp.Compare(left.GetMemory().GetUsage(), right.GetMemory().GetUsage()) }) podsByNamespace[namespace][appName] = p } @@ -358,8 +359,8 @@ func (d *discoverer) Start(ctx context.Context) (<-chan error, error) { d.eg.Go(safety.RecoverFunc(func() error { defer wg.Done() for appName, p := range podsByName { - slices.SortFunc(p, func(left, right *payload.Info_Pod) bool { - return left.GetMemory().GetUsage() < right.GetMemory().GetUsage() + slices.SortFunc(p, func(left, right *payload.Info_Pod) int { + return cmp.Compare(left.GetMemory().GetUsage(), right.GetMemory().GetUsage()) }) podsByName[appName] = p } @@ -467,16 +468,16 @@ func (d *discoverer) GetNodes(req *payload.Discoverer_Request) (nodes *payload.I for i := range ps.Pods { ps.GetPods()[i].Node = nil } - slices.SortFunc(ps.Pods, func(left, right *payload.Info_Pod) bool { - return left.GetMemory().GetUsage() < right.GetMemory().GetUsage() + slices.SortFunc(ps.Pods, func(left, right *payload.Info_Pod) int { + return cmp.Compare(left.GetMemory().GetUsage(), right.GetMemory().GetUsage()) }) n.Pods = ps } } ns = append(ns, n) } - slices.SortFunc(ns, func(left, right *payload.Info_Node) bool { - return left.GetMemory().GetUsage() < right.GetMemory().GetUsage() + slices.SortFunc(ns, func(left, right *payload.Info_Node) int { + return cmp.Compare(left.GetMemory().GetUsage(), right.GetMemory().GetUsage()) }) nodes.Nodes = ns diff --git a/pkg/gateway/filter/usecase/vald.go b/pkg/gateway/filter/usecase/vald.go index 270d0ad90f..8535fe19a0 100644 --- a/pkg/gateway/filter/usecase/vald.go +++ b/pkg/gateway/filter/usecase/vald.go @@ -18,6 +18,7 @@ package usecase import ( "context" + "slices" "github.com/vdaas/vald/apis/grpc/v1/vald" "github.com/vdaas/vald/internal/client/v1/client/filter/egress" @@ -32,7 +33,6 @@ import ( "github.com/vdaas/vald/internal/safety" "github.com/vdaas/vald/internal/servers/server" "github.com/vdaas/vald/internal/servers/starter" - "github.com/vdaas/vald/internal/slices" "github.com/vdaas/vald/internal/sync/errgroup" "github.com/vdaas/vald/pkg/gateway/filter/config" handler "github.com/vdaas/vald/pkg/gateway/filter/handler/grpc" diff --git a/pkg/gateway/lb/handler/grpc/aggregation.go b/pkg/gateway/lb/handler/grpc/aggregation.go index acfba37e5e..e29a4a46bc 100644 --- a/pkg/gateway/lb/handler/grpc/aggregation.go +++ b/pkg/gateway/lb/handler/grpc/aggregation.go @@ -580,8 +580,8 @@ func (v *valdSliceAggr) Send(ctx context.Context, data *payload.Search_Response) } func (v *valdSliceAggr) Result() (res *payload.Search_Response) { - slices.RemoveDuplicates(v.result, func(l, r *DistPayload) bool { - return l.distance.Cmp(r.distance) < 0 + slices.RemoveDuplicates(v.result, func(l, r *DistPayload) int { + return l.distance.Cmp(r.distance) }) if len(v.result) > v.num { @@ -646,8 +646,8 @@ func (v *valdPoolSliceAggr) Send(ctx context.Context, data *payload.Search_Respo } func (v *valdPoolSliceAggr) Result() (res *payload.Search_Response) { - slices.RemoveDuplicates(v.result, func(l, r *DistPayload) bool { - return l.distance.Cmp(r.distance) < 0 + slices.RemoveDuplicates(v.result, func(l, r *DistPayload) int { + return l.distance.Cmp(r.distance) }) if len(v.result) > v.num { diff --git a/pkg/gateway/lb/handler/grpc/handler.go b/pkg/gateway/lb/handler/grpc/handler.go index 0442aeceb8..27f5bf8c90 100644 --- a/pkg/gateway/lb/handler/grpc/handler.go +++ b/pkg/gateway/lb/handler/grpc/handler.go @@ -20,6 +20,7 @@ package grpc import ( "context" "fmt" + "slices" "strconv" "sync/atomic" "time" @@ -38,7 +39,6 @@ import ( "github.com/vdaas/vald/internal/net/grpc/status" "github.com/vdaas/vald/internal/observability/trace" "github.com/vdaas/vald/internal/safety" - "github.com/vdaas/vald/internal/slices" "github.com/vdaas/vald/internal/strings" "github.com/vdaas/vald/internal/sync" "github.com/vdaas/vald/internal/sync/errgroup" diff --git a/pkg/gateway/lb/handler/grpc/search_benchmark_test.go b/pkg/gateway/lb/handler/grpc/search_benchmark_test.go index 3288e04d0a..9302c2cdf0 100644 --- a/pkg/gateway/lb/handler/grpc/search_benchmark_test.go +++ b/pkg/gateway/lb/handler/grpc/search_benchmark_test.go @@ -14,17 +14,18 @@ package grpc import ( + "cmp" "context" "flag" "fmt" "runtime" + "slices" "sync/atomic" "testing" "time" "github.com/vdaas/vald/apis/grpc/v1/payload" "github.com/vdaas/vald/internal/rand" - "github.com/vdaas/vald/internal/slices" "github.com/vdaas/vald/internal/sync" "github.com/vdaas/vald/internal/sync/errgroup" "github.com/vdaas/vald/internal/test/data/strings" @@ -79,8 +80,8 @@ func newRandomResponse() (res *payload.Search_Response) { Distance: rand.Float32(), }) } - slices.SortFunc(res.Results, func(left, right *payload.Object_Distance) bool { - return left.GetDistance() < right.GetDistance() + slices.SortFunc(res.Results, func(left, right *payload.Object_Distance) int { + return cmp.Compare(left.GetDistance(), right.GetDistance()) }) return res }