From 91cede1df0f3bccea8d60adcfb1442c67aa6706c Mon Sep 17 00:00:00 2001 From: Scott McGowan Date: Thu, 27 Jan 2022 08:28:43 +0000 Subject: [PATCH 1/2] chore: add benchmark tests and notes --- README.md | 6 +- benchmark/README.md | 186 ++++++++++++++++++++++++++++++++++++ benchmark/benchmark_test.go | 141 +++++++++++++++++++++++++++ benchmark/go.mod | 16 ++++ benchmark/go.sum | 25 +++++ jsonpath_test.go | 31 ++++++ test/array_test.go | 4 + test/bracket_test.go | 4 + test/dot_test.go | 4 + test/filter_test.go | 4 + test/helper_test.go | 10 ++ test/misc_test.go | 4 + test/union_test.go | 4 + 13 files changed, 437 insertions(+), 2 deletions(-) create mode 100644 benchmark/README.md create mode 100644 benchmark/benchmark_test.go create mode 100644 benchmark/go.mod create mode 100644 benchmark/go.sum diff --git a/README.md b/README.md index 2304b63..d82b951 100644 --- a/README.md +++ b/README.md @@ -203,7 +203,9 @@ The library supports scripts and filters using a [standard script engine](script Additionally, a custom script engine can be created and passed as an additional option when compiling the JSONPath selector ```golang - +... +compiled, err := jsonpath.Compile(selector, jsonpath.ScriptEngine(customScriptEngine)) +... ``` ## History @@ -212,6 +214,6 @@ The [original specification for JSONPath](https://goessner.net/articles/JsonPath ## Hows does this compare to... -There are many [implementations](https://cburgmer.github.io/json-path-comparison/) in multiple languages so I will not claim that this library is better in any way but I believe that it is true to the original specification and was an enjoyable challenge. +There are many [implementations](https://cburgmer.github.io/json-path-comparison/) in multiple languages. Some sample benchmarks against other implementations are detailed [here](benchmark/README.md). This implementation has merit but it not the quickest golang implementation available but could be useful for those not wanting to use json marshaling. Sample queries and the expected response for this implementation compared to the community consensus are available [here](test/README.md) diff --git a/benchmark/README.md b/benchmark/README.md new file mode 100644 index 0000000..11e0d04 --- /dev/null +++ b/benchmark/README.md @@ -0,0 +1,186 @@ +# Benchmarks + +Benchmarks of this library compared to other golang implementations. + +The example selectors from the original specification along with the sample data have been used to create this data. + +If any library is not mentioned for a selector, that means that implementation returned an error of some kind + +Test of accuracy are based off of the expected response based on the original specification and the consensus from the [json-path-comparison](https://cburgmer.github.io/json-path-comparison/) + +## Command + +```bash +go test -bench=. -cpu=1 -benchmem -count=1 -benchtime=100x +``` + +## Libraries + +`github.com/PaesslerAG/jsonpath v0.1.1` +`github.com/bhmj/jsonslice v1.1.2` +`github.com/evilmonkeyinc/jsonpath v0.7.0` +`github.com/oliveagle/jsonpath v0.0.0-20180606110733-2e52cf6e6852` +`github.com/spyzhov/ajson v0.7.0` + +## TL;DR + +This implementation is slower than others, but is only one of two that has a non-error response to all sample selectors, the other being the [spyzhov/ajson](https://github.com/spyzhov/ajson) implementation which is on average twice as fast but relies on its own json marshaller (which is impressive in it's own right) + +Generally the accuracy of the implementations that could run are the same, with a minor deviation with how array ranges are handled with one, one implementation ran but did not return a response I suspect the testing method is flawed but without adequate documentation I could not confirm this. + +## Selectors + +### `$.store.book[*].author` + +Expected Response: `["Nigel Rees","Evelyn Waugh","Herman Melville","J. R. R. Tolkien"]` + +|library|ns/op|B/op|allocs/op|accurate| +|-|-|-|-|-| +|evilmonkeyinc|43551 ns/op|6496 B/op|188 allocs/op|true| +|paesslerAG|25549 ns/op|6417 B/op|131 allocs/op|false| +|bhmj|6188 ns/op|1188 B/op|14 allocs/op|true| +|spyzhov|17612 ns/op|6608 B/op|127 allocs/op|true| + + +### `$..author` + +Expected Response: `["Nigel Rees","Evelyn Waugh","Herman Melville","J. R. R. Tolkien"]` + +|library|ns/op|B/op|allocs/op|accurate| +|-|-|-|-|-| +|evilmonkeyinc|198323 ns/op|16689 B/op|458 allocs/op|true| +|paesslerAG|16293 ns/op|6361 B/op|122 allocs/op|false| +|bhmj|16665 ns/op|1554 B/op|27 allocs/op|true| +|spyzhov|20614 ns/op|7912 B/op|159 allocs/op|true| + + +### `$.store.*` + +Expected Response: `[too large]` +> the expected response is an array with two components, the bike object and and array containing the book + +|library|ns/op|B/op|allocs/op|accurate| +|-|-|-|-|-| +|evilmonkeyinc|25933 ns/op|4928 B/op|130 allocs/op|true| +|paesslerAG|16568 ns/op|6233 B/op|120 allocs/op|false| +|bhmj|8429 ns/op|3708 B/op|9 allocs/op|true| +|spyzhov|13288 ns/op|6376 B/op|117 allocs/op|true| + +### `$.store..price` + +Expected Response; `[19.95,8.95,12.99,8.99,22.99]` + +|library|ns/op|B/op|allocs/op|accurate| +|-|-|-|-|-| +|evilmonkeyinc|104648 ns/op|15673 B/op|443 allocs/op|true| +|paesslerAG|99737 ns/op|6297 B/op|125 allocs/op|false| +|bhmj|90572 ns/op|1195 B/op|28 allocs/op|true| +|spyzhov|23793 ns/op|7816 B/op|158 allocs/op|true| + +### `$..book[2]` + +Expected Response: `[{"author":"Herman Melville","category":"fiction","isbn":"0-553-21311-3","price":8.99,"title":"Moby Dick"}]` + +|library|ns/op|B/op|allocs/op|accurate| +|-|-|-|-|-| +|evilmonkeyinc|192611 ns/op|16961 B/op|471 allocs/op|true| +|paesslerAG|25408 ns/op|6545 B/op|130 allocs/op|false| +|bhmj|13719 ns/op|1260 B/op|16 allocs/op|true| +|spyzhov|130744 ns/op|7904 B/op|160 allocs/op|true| + +### `$..book[(@.length-1)]` + +Expected Response: `[{"author":"J. R. R. Tolkien","category":"fiction","isbn":"0-395-19395-8","price":22.99,"title":"The Lord of the Rings"}]` + +|library|ns/op|B/op|allocs/op|accurate| +|-|-|-|-|-| +|evilmonkeyinc|138309 ns/op|18001 B/op|542 allocs/op|true| +|spyzhov|47062 ns/op|8840 B/op|197 allocs/op|true| + +### `$..book[-1:]` + +Expected Response" `[{"author":"J. R. R. Tolkien","category":"fiction","isbn":"0-395-19395-8","price":22.99,"title":"The Lord of the Rings"}]` + +|library|ns/op|B/op|allocs/op|accurate| +|-|-|-|-|-| +|evilmonkeyinc|198634 ns/op|17201 B/op|486 allocs/op|true| +|paesslerAG|64934 ns/op|6801 B/op|137 allocs/op|false| +|bhmj|16392 ns/op|1709 B/op|22 allocs/op|note1| +|spyzhov|17658 ns/op|7968 B/op|164 allocs/op|true| + +> note1: returned an array containing the expected response, an array in an array, but the correct object + +### `$..book[0,1]` + +Expected Response: `[{"author":"Nigel Rees","category":"reference","price":8.95,"title":"Sayings of the Century"},{"author":"Evelyn Waugh","category":"fiction","price":12.99,"title":"Sword of Honour"}]` + +|library|ns/op|B/op|allocs/op|accurate| +|-|-|-|-|-| +|evilmonkeyinc|111628 ns/op|17297 B/op|489 allocs/op|true| +|paesslerAG|54361 ns/op|6817 B/op|136 allocs/op|false| +|bhmj|23537 ns/op|2285 B/op|23 allocs/op|note1| +|spyzhov|49976 ns/op|8048 B/op|165 allocs/op|true| + +> note1: returned an array containing the expected response, an array in an array, but the correct object + +### `$..book[:2]` + +Expected Response: `[{"author":"Nigel Rees","category":"reference","price":8.95,"title":"Sayings of the Century"},{"author":"Evelyn Waugh","category":"fiction","price":12.99,"title":"Sword of Honour"}]` + +|library|ns/op|B/op|allocs/op|accurate| +|-|-|-|-|-| +|evilmonkeyinc|138072 ns/op|17281 B/op|483 allocs/op|true| +|paesslerAG|28601 ns/op|6801 B/op|137 allocs/op|false| +|bhmj|21478 ns/op|2349 B/op|24 allocs/op|note1| +|spyzhov|77671 ns/op|7984 B/op|164 allocs/op|true| + +> note1: returned an array containing the expected response, an array in an array, but the correct object + +### `$..book[?(@.isbn)]` + +Expected Response: ` [{"author":"Herman Melville","category":"fiction","isbn":"0-553-21311-3","price":8.99,"title":"Moby Dick"},{"author":"J. R. R. Tolkien","category":"fiction","isbn":"0-395-19395-8","price":22.99,"title":"The Lord of the Rings"}]` + +|library|ns/op|B/op|allocs/op|accurate| +|-|-|-|-|-| +|evilmonkeyinc|211344 ns/op|20265 B/op|556 allocs/op|true| +|paesslerAG|138063 ns/op|6937 B/op|143 allocs/op|false| +|bhmj|78538 ns/op|2731 B/op|30 allocs/op|note1| +|spyzhov|71054 ns/op|8864 B/op|217 allocs/op|true| + +> note1: returned an array containing the expected response, an array in an array, but the correct object + +### `$..book[?(@.price<10)]` + +Expected Response: `{"author":"Nigel Rees","category":"reference","price":8.95,"title":"Sayings of the Century"},{"author":"Herman Melville","category":"fiction","isbn":"0-553-21311-3","price":8.99,"title":"Moby Dick"}]` + +|library|ns/op|B/op|allocs/op|accurate| +|-|-|-|-|-| +|evilmonkeyinc|282446 ns/op|20153 B/op|564 allocs/op|true| +|bhmj|79741 ns/op|2899 B/op|43 allocs/op|note1| +|spyzhov|79312 ns/op|10160 B/op|263 allocs/op|true| + +> note1: returned an array containing the expected response, an array in an array, but the correct object + +### `$..book[?(@.price<$.expensive)]` + +Expected Response: `{"author":"Nigel Rees","category":"reference","price":8.95,"title":"Sayings of the Century"},{"author":"Herman Melville","category":"fiction","isbn":"0-553-21311-3","price":8.99,"title":"Moby Dick"}]` + +|library|ns/op|B/op|allocs/op|accurate| +|-|-|-|-|-| +|evilmonkeyinc|305200 ns/op|21449 B/op|628 allocs/op|true| +|bhmj|147911 ns/op|2995 B/op|46 allocs/op|note1| +|spyzhov|232748 ns/op|10088 B/op|285 allocs/op|true| + +> note1: returned an array containing the expected response, an array in an array, but the correct object + +### `$..*` + +Expected Response: `[too large]` +> the expected response is an array that contains every value from the sample data, this will include an array, objects, and then each individual element of those collections + +|library|ns/op|B/op|allocs/op|accurate| +|-|-|-|-|-| +|evilmonkeyinc|144373 ns/op|20193 B/op|546 allocs/op|true| +|paesslerAG|32120 ns/op|6216 B/op|117 allocs/op|false| +|bhmj|78242 ns/op|31209 B/op|69 allocs/op|true| +|spyzhov|71936 ns/op|9288 B/op|187 allocs/op|true| diff --git a/benchmark/benchmark_test.go b/benchmark/benchmark_test.go new file mode 100644 index 0000000..d2c2f17 --- /dev/null +++ b/benchmark/benchmark_test.go @@ -0,0 +1,141 @@ +package benchmark + +import ( + "encoding/json" + "testing" + + paesslerAG "github.com/PaesslerAG/jsonpath" + bhmj "github.com/bhmj/jsonslice" + emi "github.com/evilmonkeyinc/jsonpath" + oliveagle "github.com/oliveagle/jsonpath" + spyzhov "github.com/spyzhov/ajson" +) + +var selectors = []string{ + "$.store.book[*].author", + "$..author", + "$.store.*", + "$.store..price", + "$..book[2]", + "$..book[(@.length-1)]", + "$..book[-1:]", + "$..book[0,1]", + "$..book[:2]", + "$..book[?(@.isbn)]", + "$..book[?(@.price<10)]", + "$..book[?(@.price<$.expensive)]", + "$..*", +} + +var sampleDataString string = `{ "store": { "book": [{ "category": "reference", "author": "Nigel Rees", "title": "Sayings of the Century", "price": 8.95 }, { "category": "fiction", "author": "Evelyn Waugh", "title": "Sword of Honour", "price": 12.99 }, { "category": "fiction", "author": "Herman Melville", "title": "Moby Dick", "isbn": "0-553-21311-3", "price": 8.99 }, { "category": "fiction", "author": "J. R. R. Tolkien", "title": "The Lord of the Rings", "isbn": "0-395-19395-8", "price": 22.99 } ], "bicycle": { "color": "red", "price": 19.95 } }, "expensive": 10 }` + +func Benchmark_Comparison(b *testing.B) { + + for _, selector := range selectors { + b.Run(selector, func(b *testing.B) { + b.Run("evilmonkeyinc", func(b *testing.B) { + var err error + for i := 0; i < b.N; i++ { + _, err = emi.QueryString(selector, sampleDataString) + } + if err != nil { + b.SkipNow() + } + }) + b.Run("paesslerAG", func(b *testing.B) { + var err error + for i := 0; i < b.N; i++ { + value := make(map[string]interface{}) + sampleData := json.Unmarshal([]byte(sampleDataString), &value) + _, err = paesslerAG.Get(selector, sampleData) + } + if err != nil { + b.SkipNow() + } + }) + b.Run("bhmj", func(b *testing.B) { + var err error + for i := 0; i < b.N; i++ { + _, err = bhmj.Get([]byte(sampleDataString), selector) + } + if err != nil { + b.SkipNow() + } + }) + b.Run("oliveagle", func(b *testing.B) { + var err error + for i := 0; i < b.N; i++ { + value := make(map[string]interface{}) + sampleData := json.Unmarshal([]byte(sampleDataString), &value) + + var compiled *oliveagle.Compiled + compiled, err = oliveagle.Compile(selector) + if err == nil { + _, err = compiled.Lookup(sampleData) + } + } + if err != nil { + b.SkipNow() + } + }) + b.Run("spyzhov", func(b *testing.B) { + var err error + for i := 0; i < b.N; i++ { + root, _ := spyzhov.Unmarshal([]byte(sampleDataString)) + _, err = root.JSONPath(selector) + } + if err != nil { + b.SkipNow() + } + }) + }) + } +} + +/** +func Test_Comparison(t *testing.T) { + + for _, selector := range selectors { + t.Run(selector, func(t *testing.T) { + + var response interface{} + + // evilmonkeyinc + obj, _ := emi.QueryString(selector, sampleDataString) + bytes, _ := json.Marshal(obj) + response = string(bytes) + fmt.Printf("%s %s %v\n", selector, "evilmonkeyinc", response) + + // paesslerAG + value := interface{}(nil) + sampleData := json.Unmarshal([]byte(sampleDataString), &value) + response, _ = paesslerAG.Get(selector, sampleData) + fmt.Printf("%s %s %v\n", selector, "paesslerAG", response) + + // bhmj + bytes, _ = bhmj.Get([]byte(sampleDataString), selector) + response = string(bytes) + fmt.Printf("%s %s %v\n", selector, "bhmj", response) + + + // oliveagle + value = make(map[string]interface{}) + sampleData = json.Unmarshal([]byte(sampleDataString), &value) + + compiled, err := oliveagle.Compile(selector) + if err == nil { + response, _ = compiled.Lookup(sampleData) + fmt.Printf("%s %s %v\n", selector, "oliveagle", response) + } else { + fmt.Printf("%s %s %v\n", selector, "oliveagle", "failed to compile") + } + + + // spyzhov + root, _ := spyzhov.Unmarshal([]byte(sampleDataString)) + response, _ = root.JSONPath(selector) + fmt.Printf("%s %s %v\n", selector, "spyzhov", response) + }) + } +} +**/ diff --git a/benchmark/go.mod b/benchmark/go.mod new file mode 100644 index 0000000..e597f53 --- /dev/null +++ b/benchmark/go.mod @@ -0,0 +1,16 @@ +module github.com/evilmonkeyinc/jsonpath/benchmark + +go 1.17 + +require ( + github.com/PaesslerAG/jsonpath v0.1.1 + github.com/bhmj/jsonslice v1.1.2 + github.com/evilmonkeyinc/jsonpath v0.7.0 + github.com/oliveagle/jsonpath v0.0.0-20180606110733-2e52cf6e6852 + github.com/spyzhov/ajson v0.7.0 +) + +require ( + github.com/PaesslerAG/gval v1.0.0 // indirect + github.com/bhmj/xpression v0.9.1 // indirect +) diff --git a/benchmark/go.sum b/benchmark/go.sum new file mode 100644 index 0000000..77c0171 --- /dev/null +++ b/benchmark/go.sum @@ -0,0 +1,25 @@ +github.com/PaesslerAG/gval v1.0.0 h1:GEKnRwkWDdf9dOmKcNrar9EA1bz1z9DqPIO1+iLzhd8= +github.com/PaesslerAG/gval v1.0.0/go.mod h1:y/nm5yEyTeX6av0OfKJNp9rBNj2XrGhAf5+v24IBN1I= +github.com/PaesslerAG/jsonpath v0.1.0/go.mod h1:4BzmtoM/PI8fPO4aQGIusjGxGir2BzcV0grWtFzq1Y8= +github.com/PaesslerAG/jsonpath v0.1.1 h1:c1/AToHQMVsduPAa4Vh6xp2U0evy4t8SWp8imEsylIk= +github.com/PaesslerAG/jsonpath v0.1.1/go.mod h1:lVboNxFGal/VwW6d9JzIy56bUsYAP6tH/x80vjnCseY= +github.com/bhmj/jsonslice v1.1.2 h1:Lzen2S9iG3HsESpiIAnTM7Obs1QiTz83ZXa5YrpTTWI= +github.com/bhmj/jsonslice v1.1.2/go.mod h1:O3ZoA0zdEefdbk1dkU5aWPOA36zQhhS/HV6RQFLTlnU= +github.com/bhmj/xpression v0.9.1 h1:N7bX/nWx9oFi/zsiMTx2ehoRApTDAWdQadq/5o2wMGk= +github.com/bhmj/xpression v0.9.1/go.mod h1:j9oYmEXJjeL9mrgW1+ZDBKJXnbupsCPGhlO9J5YhS1Q= +github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/evilmonkeyinc/jsonpath v0.7.0 h1:jHar8KiQNNhobwKpftn5SzqaVGbGbNb+pWm+BaRQiQw= +github.com/evilmonkeyinc/jsonpath v0.7.0/go.mod h1:exI6Yme6vucFk2m/1iVtxPaHGI17Dy9uWfsqbJ4iGHM= +github.com/oliveagle/jsonpath v0.0.0-20180606110733-2e52cf6e6852 h1:Yl0tPBa8QPjGmesFh1D0rDy+q1Twx6FyU7VWHi8wZbI= +github.com/oliveagle/jsonpath v0.0.0-20180606110733-2e52cf6e6852/go.mod h1:eqOVx5Vwu4gd2mmMZvVZsgIqNSaW3xxRThUJ0k/TPk4= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/spyzhov/ajson v0.7.0 h1:iDvpu9sYuWS2QvWjne/hJM7kdlgA6xyJCH7/y+kEbMI= +github.com/spyzhov/ajson v0.7.0/go.mod h1:63V+CGM6f1Bu/p4nLIN8885ojBdt88TbLoSFzyqMuVA= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/jsonpath_test.go b/jsonpath_test.go index 39b40d9..82c5b04 100644 --- a/jsonpath_test.go +++ b/jsonpath_test.go @@ -7,6 +7,37 @@ import ( "github.com/stretchr/testify/assert" ) +func Benchmark_Selector(b *testing.B) { + + selectors := []string{ + "$.store.book[*].author", + "$..author", + "$.store.*", + "$.store..price", + "$..book[2]", + "$..book[(@.length-1)]", + "$..book[-1:]", + "$..book[0,1]", + "$..book[:2]", + "$..book[?(@.isbn)]", + "$..book[?(@.price<10)]", + "$..book[?(@.price<$.expensive)]", + "$..*", + } + + for _, selector := range selectors { + b.Run(fmt.Sprintf("%s", selector), func(b *testing.B) { + var err error + for i := 0; i < b.N; i++ { + _, err = QueryString(selector, sampleDataString) + if err != nil { + b.Error() + } + } + }) + } +} + // Tests designed after the examples in the specification document // // https://goessner.net/articles/JsonPath/ diff --git a/test/array_test.go b/test/array_test.go index 106c42f..ba079bb 100644 --- a/test/array_test.go +++ b/test/array_test.go @@ -8,6 +8,10 @@ func Test_Array(t *testing.T) { batchTest(t, arrayTests) } +func Benchmark_Array(b *testing.B) { + batchBenchmark(b, arrayTests) +} + var arrayTests []testData = []testData{ { selector: "$[1:3]", diff --git a/test/bracket_test.go b/test/bracket_test.go index f6784f9..a504005 100644 --- a/test/bracket_test.go +++ b/test/bracket_test.go @@ -8,6 +8,10 @@ func Test_Bracket(t *testing.T) { batchTest(t, bracketTests) } +func Benchmark_Bracket(b *testing.B) { + batchBenchmark(b, bracketTests) +} + var bracketTests []testData = []testData{ { selector: "$['key']", diff --git a/test/dot_test.go b/test/dot_test.go index 8785375..51740ff 100644 --- a/test/dot_test.go +++ b/test/dot_test.go @@ -6,6 +6,10 @@ func Test_Dot(t *testing.T) { batchTest(t, dotTests) } +func Benchmark_Dot(b *testing.B) { + batchBenchmark(b, dotTests) +} + var dotTests []testData = []testData{ { selector: `@.a`, diff --git a/test/filter_test.go b/test/filter_test.go index 66c9023..f9e78fe 100644 --- a/test/filter_test.go +++ b/test/filter_test.go @@ -8,6 +8,10 @@ func Test_Filter(t *testing.T) { batchTest(t, filterTests) } +func Benchmark_Filter(b *testing.B) { + batchBenchmark(b, filterTests) +} + var filterTests []testData = []testData{ { selector: `$[?(@.key)]`, diff --git a/test/helper_test.go b/test/helper_test.go index 9bff922..c72f2a2 100644 --- a/test/helper_test.go +++ b/test/helper_test.go @@ -49,6 +49,16 @@ func batchTest(t *testing.T, tests []testData) { } } +func batchBenchmark(b *testing.B, tests []testData) { + for idx, test := range tests { + b.Run(fmt.Sprintf("%d", idx), func(b *testing.B) { + for n := 0; n < b.N; n++ { + jsonpath.QueryString(test.selector, test.data) + } + }) + } +} + func Test_generateReadme(t *testing.T) { header := `# Consensus Tests diff --git a/test/misc_test.go b/test/misc_test.go index d46bfc5..a9d6a4b 100644 --- a/test/misc_test.go +++ b/test/misc_test.go @@ -6,6 +6,10 @@ func Test_Misc(t *testing.T) { batchTest(t, miscTests) } +func Benchmark_Misc(b *testing.B) { + batchBenchmark(b, miscTests) +} + var miscTests []testData = []testData{ { selector: "", // empty diff --git a/test/union_test.go b/test/union_test.go index d6ac394..0555a3f 100644 --- a/test/union_test.go +++ b/test/union_test.go @@ -6,6 +6,10 @@ func Test_Union(t *testing.T) { batchTest(t, unionTests) } +func Benchmark_Union(b *testing.B) { + batchBenchmark(b, unionTests) +} + var unionTests []testData = []testData{ { selector: `$[0,1]`, From 61c897784018ab088629898d205cf73fb256b5f4 Mon Sep 17 00:00:00 2001 From: Scott McGowan Date: Thu, 27 Jan 2022 21:22:48 +0000 Subject: [PATCH 2/2] chore: add benchmark tests and notes fix formatting of readme --- benchmark/README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/benchmark/README.md b/benchmark/README.md index 11e0d04..2bab6a0 100644 --- a/benchmark/README.md +++ b/benchmark/README.md @@ -16,11 +16,11 @@ go test -bench=. -cpu=1 -benchmem -count=1 -benchtime=100x ## Libraries -`github.com/PaesslerAG/jsonpath v0.1.1` -`github.com/bhmj/jsonslice v1.1.2` -`github.com/evilmonkeyinc/jsonpath v0.7.0` -`github.com/oliveagle/jsonpath v0.0.0-20180606110733-2e52cf6e6852` -`github.com/spyzhov/ajson v0.7.0` +- `github.com/PaesslerAG/jsonpath v0.1.1` +- `github.com/bhmj/jsonslice v1.1.2` +- `github.com/evilmonkeyinc/jsonpath v0.7.0` +- `github.com/oliveagle/jsonpath v0.0.0-20180606110733-2e52cf6e6852` +- `github.com/spyzhov/ajson v0.7.0` ## TL;DR