Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

types: cache pathExpression to improve the JSON function performance #35860

Merged
merged 7 commits into from
Jul 1, 2022
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions config/const.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,3 @@ package config

// DefRowsForSampleRate is default sample rows used to calculate samplerate.
const DefRowsForSampleRate = 110000

// TrackMemWhenExceeds is the threshold when memory usage needs to be tracked.
const TrackMemWhenExceeds = 104857600 // 100MB
38 changes: 38 additions & 0 deletions types/json/path_expr.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,15 @@
package json

import (
"math"
"regexp"
"strconv"
"strings"
"sync"

"github.com/pingcap/errors"
"github.com/pingcap/tidb/util/hack"
"github.com/pingcap/tidb/util/kvcache"
)

/*
Expand Down Expand Up @@ -92,6 +96,20 @@ type PathExpression struct {
flags pathExpressionFlag
}

var peCache PathExpressionCache

type pathExpressionKey string

func (key pathExpressionKey) Hash() []byte {
return hack.Slice(string(key))
}

// PathExpressionCache is a cache for PathExpression.
type PathExpressionCache struct {
mu sync.Mutex
cache *kvcache.SimpleLRUCache
}

// popOneLeg returns a pathLeg, and a child PathExpression without that leg.
func (pe PathExpression) popOneLeg() (pathLeg, PathExpression) {
newPe := PathExpression{
Expand Down Expand Up @@ -150,6 +168,22 @@ func (pe PathExpression) ContainsAnyAsterisk() bool {
// ParseJSONPathExpr parses a JSON path expression. Returns a PathExpression
// object which can be used in JSON_EXTRACT, JSON_SET and so on.
func ParseJSONPathExpr(pathExpr string) (pe PathExpression, err error) {
peCache.mu.Lock()
val, ok := peCache.cache.Get(pathExpressionKey(pathExpr))
if ok {
peCache.mu.Unlock()
return val.(PathExpression), nil
}
peCache.mu.Unlock()

defer func() {
if err == nil {
peCache.mu.Lock()
peCache.cache.Put(pathExpressionKey(pathExpr), kvcache.Value(pe))
peCache.mu.Unlock()
}
}()

// Find the position of first '$'. If any no-blank characters in
// pathExpr[0: dollarIndex), return an ErrInvalidJSONPath error.
dollarIndex := strings.Index(pathExpr, "$")
Expand Down Expand Up @@ -261,3 +295,7 @@ func (pe PathExpression) String() string {
}
return s.String()
}

func init() {
peCache.cache = kvcache.NewSimpleLRUCache(1000, 0.1, math.MaxUint64)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Set the quota to a value like 10MB?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It has example code in the convertReadableSizeToByteSize. just some const value.

}
6 changes: 4 additions & 2 deletions util/memory/tracker.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,13 @@ import (
"sync"
"sync/atomic"

"github.com/pingcap/tidb/config"
"github.com/pingcap/tidb/metrics"
atomicutil "go.uber.org/atomic"
)

// TrackMemWhenExceeds is the threshold when memory usage needs to be tracked.
const TrackMemWhenExceeds = 104857600 // 100MB

// Tracker is used to track the memory usage during query execution.
// It contains an optional limit and can be arranged into a tree structure
// such that the consumption tracked by a Tracker is also tracked by
Expand Down Expand Up @@ -388,7 +390,7 @@ func (t *Tracker) Consume(bytes int64) {
// BufferedConsume is used to buffer memory usage and do late consume
func (t *Tracker) BufferedConsume(bufferedMemSize *int64, bytes int64) {
*bufferedMemSize += bytes
if *bufferedMemSize > int64(config.TrackMemWhenExceeds) {
if *bufferedMemSize > int64(TrackMemWhenExceeds) {
t.Consume(*bufferedMemSize)
*bufferedMemSize = int64(0)
}
Expand Down