Skip to content

Commit eb0f720

Browse files
authored
use result cache (#30)
1 parent b332223 commit eb0f720

9 files changed

+92
-57
lines changed

buffer_container.go

-33
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,5 @@
11
package jsonpath
22

3-
import (
4-
"sort"
5-
"sync"
6-
)
7-
83
type bufferContainer struct {
94
result []interface{}
105
}
11-
12-
var bufferContainerSortSliceSyncPool = &sync.Pool{
13-
New: func() interface{} { return new(sort.StringSlice) },
14-
}
15-
16-
func (b *bufferContainer) getSortedKeys(srcMap map[string]interface{}) *sort.StringSlice {
17-
length := len(srcMap)
18-
sortKeys := bufferContainerSortSliceSyncPool.Get().(*sort.StringSlice)
19-
if cap(*sortKeys) < length {
20-
*sortKeys = make(sort.StringSlice, length)
21-
}
22-
*sortKeys = (*sortKeys)[:length]
23-
index := 0
24-
for key := range srcMap {
25-
(*sortKeys)[index] = key
26-
index++
27-
}
28-
if length > 1 {
29-
sortKeys.Sort()
30-
}
31-
return sortKeys
32-
}
33-
34-
func (b *bufferContainer) putSortSlice(sortKeys *sort.StringSlice) {
35-
if sortKeys != nil {
36-
bufferContainerSortSliceSyncPool.Put(sortKeys)
37-
}
38-
}

cache.go

+47
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
package jsonpath
2+
3+
import (
4+
"sort"
5+
"sync"
6+
)
7+
8+
var sortSliceSyncPool = &sync.Pool{
9+
New: func() interface{} { return new(sort.StringSlice) },
10+
}
11+
12+
var resultSyncPool = &sync.Pool{
13+
New: func() interface{} { return new(bufferContainer) },
14+
}
15+
16+
func getSortedKeys(srcMap map[string]interface{}) *sort.StringSlice {
17+
length := len(srcMap)
18+
sortKeys := sortSliceSyncPool.Get().(*sort.StringSlice)
19+
if cap(*sortKeys) < length {
20+
*sortKeys = make(sort.StringSlice, length)
21+
}
22+
*sortKeys = (*sortKeys)[:length]
23+
index := 0
24+
for key := range srcMap {
25+
(*sortKeys)[index] = key
26+
index++
27+
}
28+
if length > 1 {
29+
sortKeys.Sort()
30+
}
31+
return sortKeys
32+
}
33+
34+
func putSortSlice(sortKeys *sort.StringSlice) {
35+
if sortKeys != nil {
36+
sortSliceSyncPool.Put(sortKeys)
37+
}
38+
}
39+
40+
func getContainer() *bufferContainer {
41+
return resultSyncPool.Get().(*bufferContainer)
42+
}
43+
44+
func putContainer(container *bufferContainer) {
45+
container.result = container.result[:0]
46+
resultSyncPool.Put(container)
47+
}

jsonpath.go

+13-5
Original file line numberDiff line numberDiff line change
@@ -52,13 +52,21 @@ func Parse(jsonPath string, config ...Config) (f func(src interface{}) ([]interf
5252

5353
root := parser.jsonPathParser.root
5454
return func(src interface{}) ([]interface{}, error) {
55-
container := bufferContainer{}
55+
container := getContainer()
56+
defer func() {
57+
putContainer(container)
58+
}()
5659

57-
err := root.retrieve(src, src, &container)
58-
if err != nil {
59-
return container.result, err.(error)
60+
if err := root.retrieve(src, src, container); err != nil {
61+
return nil, err.(error)
6062
}
61-
return container.result, nil
63+
64+
result := make([]interface{}, len(container.result))
65+
for index := range result {
66+
result[index] = container.result[index]
67+
}
68+
69+
return result, nil
6270

6371
}, nil
6472
}

syntax_node_function_aggregate.go

+8-4
Original file line numberDiff line numberDiff line change
@@ -10,19 +10,23 @@ type syntaxAggregateFunction struct {
1010
func (f *syntaxAggregateFunction) retrieve(
1111
root, current interface{}, container *bufferContainer) errorRuntime {
1212

13-
values := bufferContainer{}
13+
values := getContainer()
14+
defer func() {
15+
putContainer(values)
16+
}()
1417

15-
if err := f.param.retrieve(root, current, &values); err != nil {
18+
if err := f.param.retrieve(root, current, values); err != nil {
1619
return err
1720
}
1821

22+
result := values.result
1923
if !f.param.isValueGroup() {
2024
if arrayParam, ok := values.result[0].([]interface{}); ok {
21-
values.result = arrayParam
25+
result = arrayParam
2226
}
2327
}
2428

25-
filteredValue, err := f.function(values.result)
29+
filteredValue, err := f.function(result)
2630
if err != nil {
2731
return ErrorFunctionFailed{
2832
errorBasicRuntime: f.errorRuntime,

syntax_node_identifier_child_wildcard.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ func (i *syntaxChildWildcardIdentifier) retrieveMap(
3737
var deepestTextLen int
3838
var deepestError errorRuntime
3939

40-
sortKeys := container.getSortedKeys(srcMap)
40+
sortKeys := getSortedKeys(srcMap)
4141

4242
for _, key := range *sortKeys {
4343
if err := i.retrieveMapNext(root, srcMap, key, container); err != nil {
@@ -47,7 +47,7 @@ func (i *syntaxChildWildcardIdentifier) retrieveMap(
4747
}
4848
}
4949

50-
container.putSortSlice(sortKeys)
50+
putSortSlice(sortKeys)
5151

5252
if len(container.result) > 0 {
5353
return nil

syntax_node_identifier_recursive_child.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ func (i *syntaxRecursiveChildIdentifier) retrieve(
4747
}
4848
}
4949

50-
sortKeys := container.getSortedKeys(typedNodes)
50+
sortKeys := getSortedKeys(typedNodes)
5151
for index := len(typedNodes) - 1; index >= 0; index-- {
5252
node := typedNodes[(*sortKeys)[index]]
5353
switch node.(type) {
@@ -56,7 +56,7 @@ func (i *syntaxRecursiveChildIdentifier) retrieve(
5656
}
5757
}
5858

59-
container.putSortSlice(sortKeys)
59+
putSortSlice(sortKeys)
6060

6161
case []interface{}:
6262
if i.nextListRequired {

syntax_node_qualifier_filter.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ func (f *syntaxFilterQualifier) retrieveMap(
3737
var deepestTextLen int
3838
var deepestError errorRuntime
3939

40-
sortKeys := container.getSortedKeys(srcMap)
40+
sortKeys := getSortedKeys(srcMap)
4141

4242
valueList := make([]interface{}, len(*sortKeys))
4343
for index := range *sortKeys {
@@ -69,7 +69,7 @@ func (f *syntaxFilterQualifier) retrieveMap(
6969
}
7070
}
7171

72-
container.putSortSlice(sortKeys)
72+
putSortSlice(sortKeys)
7373

7474
if len(container.result) > 0 {
7575
return nil

syntax_query_param_current_root.go

+13-7
Original file line numberDiff line numberDiff line change
@@ -12,23 +12,29 @@ func (e *syntaxQueryParamCurrentRoot) compute(
1212
root interface{}, currentList []interface{}) []interface{} {
1313

1414
result := make([]interface{}, len(currentList))
15-
containers := make([]bufferContainer, len(currentList))
1615

1716
var hasValue bool
17+
18+
container := getContainer()
19+
defer func() {
20+
putContainer(container)
21+
}()
22+
1823
for index := range currentList {
19-
if e.param.retrieve(root, currentList[index], &containers[index]) != nil {
24+
container.result = container.result[:0]
25+
if e.param.retrieve(root, currentList[index], container) != nil {
2026
result[index] = emptyEntity
2127
continue
2228
}
2329
hasValue = true
24-
if e.param.isValueGroup() {
25-
result[index] = containers[index].result
26-
} else {
27-
result[index] = containers[index].result[0]
28-
}
30+
// If e.param.isValueGroup==true,
31+
// Only the first element is returned because it is an existence check.
32+
result[index] = container.result[0]
2933
}
34+
3035
if hasValue {
3136
return result
3237
}
38+
3339
return emptyList
3440
}

syntax_query_param_root.go

+5-2
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,12 @@ func (e *syntaxQueryParamRoot) isValueGroupParameter() bool {
1111
func (e *syntaxQueryParamRoot) compute(
1212
root interface{}, currentList []interface{}) []interface{} {
1313

14-
values := bufferContainer{}
14+
values := getContainer()
15+
defer func() {
16+
putContainer(values)
17+
}()
1518

16-
if e.param.retrieve(root, root, &values) != nil {
19+
if e.param.retrieve(root, root, values) != nil {
1720
return emptyList
1821
}
1922

0 commit comments

Comments
 (0)