Skip to content

Commit

Permalink
planner: add monitor for prepared plan cache memory usage (#38507)
Browse files Browse the repository at this point in the history
ref #37632
  • Loading branch information
fzzf678 committed Nov 2, 2022
1 parent ba175c4 commit a3d7420
Show file tree
Hide file tree
Showing 6 changed files with 269 additions and 17 deletions.
211 changes: 211 additions & 0 deletions metrics/grafana/tidb.json
Original file line number Diff line number Diff line change
Expand Up @@ -7473,6 +7473,217 @@
"align": false,
"alignLevel": null
}
},
{
"aliasColors": {},
"bars": false,
"dashLength": 10,
"dashes": false,
"datasource": "${DS_TEST-CLUSTER}",
"description": "Total memory usage of all prepared plan cache in a instance",
"fieldConfig": {
"defaults": {},
"overrides": []
},
"fill": 1,
"fillGradient": 0,
"gridPos": {
"h": 8,
"w": 12,
"x": 12,
"y": 29
},
"hiddenSeries": false,
"id": 269,
"legend": {
"alignAsTable": true,
"avg": false,
"current": true,
"hideEmpty": true,
"max": true,
"min": false,
"rightSide": true,
"show": true,
"total": false,
"values": true
},
"lines": true,
"linewidth": 1,
"nullPointMode": "null as zero",
"options": {
"alertThreshold": true
},
"percentage": false,
"pluginVersion": "7.5.11",
"pointradius": 2,
"points": false,
"renderer": "flot",
"seriesOverrides": [],
"spaceLength": 10,
"stack": false,
"steppedLine": false,
"targets": [
{
"exemplar": true,
"expr": "tidb_server_plan_cache_instance_memory_usage{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\"}",
"hide": false,
"interval": "",
"legendFormat": "{{instance}}",
"refId": "A"
}
],
"thresholds": [],
"timeFrom": null,
"timeRegions": [],
"timeShift": null,
"title": "Plan Cache Memory Usage",
"tooltip": {
"shared": true,
"sort": 0,
"value_type": "individual"
},
"type": "graph",
"xaxis": {
"buckets": null,
"mode": "time",
"name": null,
"show": true,
"values": []
},
"yaxes": [
{
"$$hashKey": "object:122",
"format": "bytes",
"label": null,
"logBase": 1,
"max": null,
"min": "0",
"show": true
},
{
"$$hashKey": "object:123",
"format": "short",
"label": null,
"logBase": 1,
"max": null,
"min": null,
"show": true
}
],
"yaxis": {
"align": false,
"alignLevel": null
}
},
{
"aliasColors": {},
"bars": false,
"dashLength": 10,
"dashes": false,
"datasource": "${DS_TEST-CLUSTER}",
"decimals": null,
"description": "TiDB prepared plan cache plan num\n",
"editable": true,
"error": false,
"fieldConfig": {
"defaults": {},
"overrides": []
},
"fill": 1,
"fillGradient": 0,
"grid": {},
"gridPos": {
"h": 8,
"w": 12,
"x": 0,
"y": 37
},
"hiddenSeries": false,
"id": 271,
"legend": {
"alignAsTable": true,
"avg": false,
"current": true,
"hideEmpty": true,
"hideZero": true,
"max": true,
"min": false,
"rightSide": true,
"show": true,
"sort": null,
"sortDesc": null,
"total": false,
"values": true
},
"lines": true,
"linewidth": 1,
"links": [],
"nullPointMode": "null as zero",
"options": {
"alertThreshold": true
},
"percentage": false,
"pluginVersion": "7.5.11",
"pointradius": 5,
"points": false,
"renderer": "flot",
"seriesOverrides": [],
"spaceLength": 10,
"stack": false,
"steppedLine": false,
"targets": [
{
"exemplar": true,
"expr": "tidb_server_plan_cache_instance_plan_num_total{k8s_cluster=\"$k8s_cluster\", tidb_cluster=\"$tidb_cluster\", instance=~\"$instance\"}\n",
"format": "time_series",
"interval": "",
"intervalFactor": 2,
"legendFormat": "{{instance}}",
"refId": "A",
"step": 30
}
],
"thresholds": [],
"timeFrom": null,
"timeRegions": [],
"timeShift": null,
"title": "Plan Cache Plan Num",
"tooltip": {
"msResolution": false,
"shared": true,
"sort": 0,
"value_type": "cumulative"
},
"type": "graph",
"xaxis": {
"buckets": null,
"mode": "time",
"name": null,
"show": true,
"values": []
},
"yaxes": [
{
"format": "short",
"label": null,
"logBase": 1,
"max": null,
"min": "0",
"show": true
},
{
"format": "short",
"label": null,
"logBase": 1,
"max": null,
"min": null,
"show": true
}
],
"yaxis": {
"align": false,
"alignLevel": null
}
}
],
"repeat": null,
Expand Down
2 changes: 2 additions & 0 deletions metrics/metrics.go
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,8 @@ func RegisterMetrics() {
prometheus.MustRegister(PanicCounter)
prometheus.MustRegister(PlanCacheCounter)
prometheus.MustRegister(PlanCacheMissCounter)
prometheus.MustRegister(PlanCacheInstanceMemoryUsage)
prometheus.MustRegister(PlanCacheInstancePlanNumCounter)
prometheus.MustRegister(PseudoEstimation)
prometheus.MustRegister(PacketIOCounter)
prometheus.MustRegister(QueryDurationHistogram)
Expand Down
16 changes: 16 additions & 0 deletions metrics/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,22 @@ var (
Help: "Counter of plan cache miss.",
}, []string{LblType})

PlanCacheInstanceMemoryUsage = prometheus.NewGaugeVec(
prometheus.GaugeOpts{
Namespace: "tidb",
Subsystem: "server",
Name: "plan_cache_instance_memory_usage",
Help: "Total plan cache memory usage of all sessions in a instance",
}, []string{LblType})

PlanCacheInstancePlanNumCounter = prometheus.NewGaugeVec(
prometheus.GaugeOpts{
Namespace: "tidb",
Subsystem: "server",
Name: "plan_cache_instance_plan_num_total",
Help: "Counter of plan of all prepared plan cache in a instance",
}, []string{LblType})

ReadFromTableCacheCounter = prometheus.NewCounter(
prometheus.CounterOpts{
Namespace: "tidb",
Expand Down
53 changes: 36 additions & 17 deletions planner/core/plan_cache_lru.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import (
"sync"

"github.com/pingcap/errors"
"github.com/pingcap/tidb/metrics"
"github.com/pingcap/tidb/types"
"github.com/pingcap/tidb/util/hack"
"github.com/pingcap/tidb/util/kvcache"
Expand Down Expand Up @@ -59,8 +60,7 @@ type LRUPlanCache struct {
quota uint64
guard float64

// MemTracker track the memory usage of prepared plan cache
memTracker *memory.Tracker
memoryUsageTotal int64
}

// NewLRUPlanCache creates a PCLRUCache object, whose capacity is "capacity".
Expand All @@ -71,7 +71,6 @@ func NewLRUPlanCache(capacity uint, guard float64, quota uint64,
capacity = 100
logutil.BgLogger().Info("capacity of LRU cache is less than 1, will use default value(100) init cache")
}

return &LRUPlanCache{
capacity: capacity,
size: 0,
Expand All @@ -80,7 +79,6 @@ func NewLRUPlanCache(capacity uint, guard float64, quota uint64,
pickFromBucket: pickFromBucket,
quota: quota,
guard: guard,
memTracker: newTrackerForLRUPC(),
}
}

Expand Down Expand Up @@ -116,8 +114,7 @@ func (l *LRUPlanCache) Put(key kvcache.Key, value kvcache.Value, paramTypes []*t
bucket, bucketExist := l.buckets[hash]
if bucketExist {
if element, exist := l.pickFromBucket(bucket, paramTypes); exist {
l.memTracker.Consume(value.(*PlanCacheValue).MemoryUsage() -
element.Value.(*planCacheEntry).PlanValue.(*PlanCacheValue).MemoryUsage())
l.updateInstanceMetric(&planCacheEntry{PlanKey: key, PlanValue: value}, element.Value.(*planCacheEntry))
element.Value.(*planCacheEntry).PlanValue = value
l.lruList.MoveToFront(element)
return
Expand All @@ -133,7 +130,7 @@ func (l *LRUPlanCache) Put(key kvcache.Key, value kvcache.Value, paramTypes []*t
element := l.lruList.PushFront(newCacheEntry)
l.buckets[hash][element] = struct{}{}
l.size++
l.memTracker.Consume(newCacheEntry.MemoryUsage())
l.updateInstanceMetric(newCacheEntry, nil)
if l.size > l.capacity {
l.removeOldest()
}
Expand All @@ -149,7 +146,7 @@ func (l *LRUPlanCache) Delete(key kvcache.Key) {
bucket, bucketExist := l.buckets[hash]
if bucketExist {
for element := range bucket {
l.memTracker.Consume(-element.Value.(*planCacheEntry).MemoryUsage())
l.updateInstanceMetric(nil, element.Value.(*planCacheEntry))
l.lruList.Remove(element)
l.size--
}
Expand All @@ -163,11 +160,11 @@ func (l *LRUPlanCache) DeleteAll() {
defer l.lock.Unlock()

for lru := l.lruList.Back(); lru != nil; lru = l.lruList.Back() {
l.updateInstanceMetric(nil, lru.Value.(*planCacheEntry))
l.lruList.Remove(lru)
l.size--
}
l.buckets = make(map[string]map[*list.Element]struct{}, 1)
l.memTracker = newTrackerForLRUPC()
}

// Size gets the current cache size.
Expand Down Expand Up @@ -198,7 +195,16 @@ func (l *LRUPlanCache) MemoryUsage() (sum int64) {
if l == nil {
return
}
return l.memTracker.BytesConsumed()
return l.memoryUsageTotal
}

// Close do some clean work for LRUPlanCache when close the session
func (l *LRUPlanCache) Close() {
if l == nil {
return
}
metrics.PlanCacheInstanceMemoryUsage.WithLabelValues("instance").Sub(float64(l.memoryUsageTotal))
metrics.PlanCacheInstancePlanNumCounter.WithLabelValues("plan_num").Sub(float64(l.size))
}

// removeOldest removes the oldest element from the cache.
Expand All @@ -211,7 +217,7 @@ func (l *LRUPlanCache) removeOldest() {
l.onEvict(lru.Value.(*planCacheEntry).PlanKey, lru.Value.(*planCacheEntry).PlanValue)
}

l.memTracker.Consume(-lru.Value.(*planCacheEntry).MemoryUsage())
l.updateInstanceMetric(nil, lru.Value.(*planCacheEntry))
l.lruList.Remove(lru)
l.removeFromBucket(lru)
l.size--
Expand Down Expand Up @@ -251,10 +257,23 @@ func PickPlanFromBucket(bucket map[*list.Element]struct{}, paramTypes []*types.F
return nil, false
}

// newTrackerForLRUPC return a tracker which consumed emptyLRUPlanCacheSize
// todo: pass label when track general plan cache memory
func newTrackerForLRUPC() *memory.Tracker {
m := memory.NewTracker(memory.LabelForPreparedPlanCache, -1)
//todo: maybe need attach here
return m
// updateInstanceMetric update the memory usage and plan num for show in grafana
func (l *LRUPlanCache) updateInstanceMetric(in, out *planCacheEntry) {
if l == nil {
return
}

if in != nil && out != nil { // replace plan
metrics.PlanCacheInstanceMemoryUsage.WithLabelValues("instance").Sub(float64(out.MemoryUsage()))
metrics.PlanCacheInstanceMemoryUsage.WithLabelValues("instance").Add(float64(in.MemoryUsage()))
l.memoryUsageTotal += in.MemoryUsage() - out.MemoryUsage()
} else if in != nil { // put plan
metrics.PlanCacheInstanceMemoryUsage.WithLabelValues("instance").Add(float64(in.MemoryUsage()))
l.memoryUsageTotal += in.MemoryUsage()
metrics.PlanCacheInstancePlanNumCounter.WithLabelValues("plan_num").Add(1)
} else { // delete plan
metrics.PlanCacheInstanceMemoryUsage.WithLabelValues("instance").Sub(float64(out.MemoryUsage()))
l.memoryUsageTotal -= out.MemoryUsage()
metrics.PlanCacheInstancePlanNumCounter.WithLabelValues("plan_num").Sub(1)
}
}
3 changes: 3 additions & 0 deletions session/session.go
Original file line number Diff line number Diff line change
Expand Up @@ -2572,6 +2572,9 @@ func (s *session) Close() {
s.stmtStats.SetFinished()
}
s.ClearDiskFullOpt()
if s.preparedPlanCache != nil {
s.preparedPlanCache.Close()
}
}

// GetSessionVars implements the context.Context interface.
Expand Down
1 change: 1 addition & 0 deletions sessionctx/context.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ type PlanCache interface {
DeleteAll()
Size() int
SetCapacity(capacity uint) error
Close()
}

// Context is an interface for transaction and executive args environment.
Expand Down

0 comments on commit a3d7420

Please sign in to comment.