diff --git a/internal/knn/knn_test.go b/internal/knn/knn_test.go index 6b44426..260c7fc 100644 --- a/internal/knn/knn_test.go +++ b/internal/knn/knn_test.go @@ -13,7 +13,7 @@ import ( "github.com/downflux/go-kd/point" "github.com/google/go-cmp/cmp" - mock "github.com/downflux/go-kd/internal/point/testdata/mock" + mock "github.com/downflux/go-kd/internal/point/testdata/mock/simple" ) func TestPath(t *testing.T) { diff --git a/internal/node/node_test.go b/internal/node/node_test.go index 74a57c5..f290ea2 100644 --- a/internal/node/node_test.go +++ b/internal/node/node_test.go @@ -8,7 +8,7 @@ import ( "github.com/downflux/go-kd/point" "github.com/google/go-cmp/cmp" - mock "github.com/downflux/go-kd/internal/point/testdata/mock" + mock "github.com/downflux/go-kd/internal/point/testdata/mock/simple" ) func TestNew(t *testing.T) { diff --git a/internal/point/sorter/sorter_test.go b/internal/point/sorter/sorter_test.go index 09a6b63..83f1985 100644 --- a/internal/point/sorter/sorter_test.go +++ b/internal/point/sorter/sorter_test.go @@ -10,7 +10,7 @@ import ( "github.com/google/go-cmp/cmp" "github.com/kyroy/kdtree" - mock "github.com/downflux/go-kd/internal/point/testdata/mock" + mock "github.com/downflux/go-kd/internal/point/testdata/mock/simple" ) const ( diff --git a/internal/point/testdata/mock/multifield/point.go b/internal/point/testdata/mock/multifield/point.go new file mode 100644 index 0000000..0caec01 --- /dev/null +++ b/internal/point/testdata/mock/multifield/point.go @@ -0,0 +1,50 @@ +package point + +import ( + "time" + + "github.com/downflux/go-geometry/nd/vector" + "github.com/downflux/go-kd/point" +) + +const ( + // etag is base58-encoded "flames on the side of my face". + etag = "5ege8ja1nQTnQ8rvMtbyJ9FKgTtibTPJc4CUKJZa" +) + +var _ point.P = &P{} + +type P struct { + id int + comment string + etag string + modified bool + metadata map[string]string + timestamp time.Time + + p vector.V +} + +func New(p vector.V, name string) *P { + return &P{ + p: p, + comment: name, + timestamp: time.Now(), + metadata: map[string]string{ + "Mrs. Peacock": "Eileen Brennan", + "Mrs. White": "Madeline Kahn", + "Professor Plum": "Christopher Lloyd", + "Mr. Green": "Michael McKean", + "Colonel Mustard": "Martin Mull", + "Miss Scarlet": "Lesley Ann Warren", + + "Mr. Boddy": "Lee Ving", + "Yvette": "Colleen Camp", + "Wadsworth": "SPAAAAAAAACE", + }, + + etag: etag, + } +} + +func (p *P) P() vector.V { return p.p } diff --git a/internal/point/testdata/mock/point.go b/internal/point/testdata/mock/simple/point.go similarity index 84% rename from internal/point/testdata/mock/point.go rename to internal/point/testdata/mock/simple/point.go index 97ae875..0ed4e37 100644 --- a/internal/point/testdata/mock/point.go +++ b/internal/point/testdata/mock/simple/point.go @@ -7,6 +7,8 @@ import ( "github.com/downflux/go-kd/point" ) +var _ point.P = P{} + type P struct { p vector.V hash string @@ -15,7 +17,7 @@ type P struct { func (p P) P() vector.V { return p.p } func (p P) Hash() string { return p.hash } -func New(p vector.V, hash string) *P { return &P{p: p, hash: hash} } +func New(p vector.V, hash string) *P { return &P{p: p, hash: hash} } // CheckHash may be passed into the K-D tree API as the filter function for this // data struct. diff --git a/internal/pq/pq_test.go b/internal/pq/pq_test.go index 6af6d24..edca436 100644 --- a/internal/pq/pq_test.go +++ b/internal/pq/pq_test.go @@ -8,7 +8,7 @@ import ( "github.com/downflux/go-kd/point" "github.com/google/go-cmp/cmp" - mock "github.com/downflux/go-kd/internal/point/testdata/mock" + mock "github.com/downflux/go-kd/internal/point/testdata/mock/simple" ) type item struct { diff --git a/internal/rangesearch/rangesearch_test.go b/internal/rangesearch/rangesearch_test.go index dc355b3..6e45cd6 100644 --- a/internal/rangesearch/rangesearch_test.go +++ b/internal/rangesearch/rangesearch_test.go @@ -9,7 +9,7 @@ import ( "github.com/downflux/go-kd/point" "github.com/google/go-cmp/cmp" - mock "github.com/downflux/go-kd/internal/point/testdata/mock" + mock "github.com/downflux/go-kd/internal/point/testdata/mock/simple" ) func TestSearch(t *testing.T) { diff --git a/internal/testdata/generator/generator.go b/internal/testdata/generator/generator.go index 6a4a0e7..6895fc0 100644 --- a/internal/testdata/generator/generator.go +++ b/internal/testdata/generator/generator.go @@ -10,7 +10,8 @@ import ( "github.com/kyroy/kdtree" "github.com/kyroy/kdtree/points" - mock "github.com/downflux/go-kd/internal/point/testdata/mock" + simple "github.com/downflux/go-kd/internal/point/testdata/mock/simple" + multifield "github.com/downflux/go-kd/internal/point/testdata/mock/multifield" ) const ( @@ -33,6 +34,24 @@ func V(d vector.D) vector.V { return vector.V(xs) } +// C generates a slice of multifield points satisfying the point.P interface. We +// use this to detect potential issues with how the K-D tree handles pointers to +// points, per +// https://github.com/downflux/go-kd/issues/3#issuecomment-974496706. +func C(n int, d vector.D) []point.P { + // Generating large number of points in tests will mess with data + // collection figures. We should ignore these allocs. + runtime.MemProfileRate = 0 + defer func() { runtime.MemProfileRate = 512 * 1024 }() + + ps := make([]point.P, n) + for i := 0; i < n; i++ { + ps[i] = multifield.New(V(d), fmt.Sprintf("Random-%v", i)) + } + return ps +} + +// P generates a slice of simple points satisfying the point.P interface. func P(n int, d vector.D) []point.P { // Generating large number of points in tests will mess with data // collection figures. We should ignore these allocs. @@ -41,7 +60,7 @@ func P(n int, d vector.D) []point.P { ps := make([]point.P, n) for i := 0; i < n; i++ { - ps[i] = *mock.New(V(d), fmt.Sprintf("Random-%v", i)) + ps[i] = *simple.New(V(d), fmt.Sprintf("Random-%v", i)) } return ps } diff --git a/kd/kd_test.go b/kd/kd_test.go index c44afb2..c5c1b58 100644 --- a/kd/kd_test.go +++ b/kd/kd_test.go @@ -11,7 +11,7 @@ import ( "github.com/downflux/go-kd/internal/testdata/generator" "github.com/downflux/go-kd/point" - mock "github.com/downflux/go-kd/internal/point/testdata/mock" + mock "github.com/downflux/go-kd/internal/point/testdata/mock/simple" ) const ( @@ -95,11 +95,21 @@ func BenchmarkNew(b *testing.B) { for _, c := range testConfigs { ps := generator.P(c.n, vector.D(c.k)) + cs := generator.C(c.n, vector.D(c.k)) + b.Run(c.name, func(b *testing.B) { for i := 0; i < b.N; i++ { New(ps) } }) + + // Check tree construction times with more complex point.P + // implementations. + b.Run(fmt.Sprintf("%v/MultiField", c.name), func(b *testing.B) { + for i := 0; i < b.N; i++ { + New(cs) + } + }) } }