Skip to content

Commit 25a51b9

Browse files
djshow832xhebox
andauthored
backend: optimize updating command metrics (#467)
Co-authored-by: xhe <[email protected]>
1 parent 7443ce6 commit 25a51b9

File tree

2 files changed

+139
-4
lines changed

2 files changed

+139
-4
lines changed

pkg/proxy/backend/metrics.go

Lines changed: 38 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,21 +4,55 @@
44
package backend
55

66
import (
7+
"sync"
78
"time"
89

910
"github.com/pingcap/tiproxy/pkg/metrics"
1011
pnet "github.com/pingcap/tiproxy/pkg/proxy/net"
1112
"github.com/pingcap/tiproxy/pkg/util/monotime"
13+
"github.com/prometheus/client_golang/prometheus"
1214
)
1315

14-
func addCmdMetrics(cmd pnet.Command, addr string, startTime monotime.Time) {
15-
label := cmd.String()
16-
metrics.QueryTotalCounter.WithLabelValues(addr, label).Inc()
16+
type mcPerCmd struct {
17+
counter prometheus.Counter
18+
observer prometheus.Observer
19+
}
1720

21+
type cmdMetricsCache struct {
22+
sync.Mutex
1823
// The duration labels are different with TiDB: Labels in TiDB are statement types.
1924
// However, the proxy is not aware of the statement types, so we use command types instead.
25+
metrics map[string]*[pnet.ComEnd]mcPerCmd
26+
}
27+
28+
func newCmdMetricsCache() cmdMetricsCache {
29+
return cmdMetricsCache{
30+
metrics: make(map[string]*[pnet.ComEnd]mcPerCmd),
31+
}
32+
}
33+
34+
var cache = newCmdMetricsCache()
35+
36+
func addCmdMetrics(cmd pnet.Command, addr string, startTime monotime.Time) {
37+
cache.Lock()
38+
defer cache.Unlock()
39+
40+
addrMc, ok := cache.metrics[addr]
41+
if !ok {
42+
addrMc = &[pnet.ComEnd]mcPerCmd{}
43+
cache.metrics[addr] = addrMc
44+
}
45+
mc := &addrMc[cmd]
46+
if mc.counter == nil {
47+
label := cmd.String()
48+
*mc = mcPerCmd{
49+
counter: metrics.QueryTotalCounter.WithLabelValues(addr, label),
50+
observer: metrics.QueryDurationHistogram.WithLabelValues(addr, label),
51+
}
52+
}
53+
mc.counter.Inc()
2054
cost := monotime.Since(startTime)
21-
metrics.QueryDurationHistogram.WithLabelValues(addr, label).Observe(cost.Seconds())
55+
mc.observer.Observe(cost.Seconds())
2256
}
2357

2458
func readCmdCounter(cmd pnet.Command, addr string) (int, error) {

pkg/proxy/backend/metrics_test.go

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
// Copyright 2024 PingCAP, Inc.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
package backend
5+
6+
import (
7+
"sync"
8+
"testing"
9+
10+
"github.com/pingcap/tiproxy/pkg/metrics"
11+
pnet "github.com/pingcap/tiproxy/pkg/proxy/net"
12+
"github.com/pingcap/tiproxy/pkg/util/monotime"
13+
"github.com/prometheus/client_golang/prometheus"
14+
)
15+
16+
func BenchmarkAddCmdMetrics(b *testing.B) {
17+
cmd := pnet.ComQuery
18+
addr := "127.0.0.1:4000"
19+
startTime := monotime.Now()
20+
for i := 0; i < b.N; i++ {
21+
addCmdMetrics(cmd, addr, startTime)
22+
}
23+
}
24+
25+
func BenchmarkAddCmdMetricsArrayPointer(b *testing.B) {
26+
cmd := pnet.ComQuery
27+
addr := "127.0.0.1:4000"
28+
var lock sync.Mutex
29+
counter := make(map[string]*[pnet.ComEnd]prometheus.Counter)
30+
for i := 0; i < b.N; i++ {
31+
lock.Lock()
32+
33+
addrCounter, ok := counter[addr]
34+
if !ok {
35+
addrCounter = &[pnet.ComEnd]prometheus.Counter{}
36+
counter[addr] = addrCounter
37+
}
38+
counter := addrCounter[cmd]
39+
if counter == nil {
40+
counter = metrics.QueryTotalCounter.WithLabelValues(addr, cmd.String())
41+
addrCounter[cmd] = counter
42+
}
43+
counter.Inc()
44+
45+
lock.Unlock()
46+
}
47+
}
48+
49+
func BenchmarkAddCmdMetricsArray(b *testing.B) {
50+
cmd := pnet.ComQuery
51+
addr := "127.0.0.1:4000"
52+
var lock sync.Mutex
53+
counter := make(map[string][pnet.ComEnd]prometheus.Counter)
54+
for i := 0; i < b.N; i++ {
55+
lock.Lock()
56+
57+
addrCounter, ok := counter[addr]
58+
if !ok {
59+
addrCounter = [pnet.ComEnd]prometheus.Counter{}
60+
counter[addr] = addrCounter
61+
}
62+
counter := addrCounter[cmd]
63+
if counter == nil {
64+
counter = metrics.QueryTotalCounter.WithLabelValues(addr, cmd.String())
65+
addrCounter[cmd] = counter
66+
}
67+
counter.Inc()
68+
69+
lock.Unlock()
70+
}
71+
}
72+
73+
func BenchmarkAddCmdMetricsMap(b *testing.B) {
74+
cmd := pnet.ComQuery
75+
addr := "127.0.0.1:4000"
76+
var lock sync.Mutex
77+
counter := make(map[string]map[pnet.Command]prometheus.Counter)
78+
for i := 0; i < b.N; i++ {
79+
lock.Lock()
80+
81+
addrCounter, ok := counter[addr]
82+
if !ok {
83+
addrCounter = make(map[pnet.Command]prometheus.Counter)
84+
counter[addr] = addrCounter
85+
}
86+
counter, ok := addrCounter[cmd]
87+
if !ok {
88+
counter = metrics.QueryTotalCounter.WithLabelValues(addr, cmd.String())
89+
addrCounter[cmd] = counter
90+
}
91+
counter.Inc()
92+
93+
lock.Unlock()
94+
}
95+
}
96+
97+
func BenchmarkAddCmdMetricsSimple(b *testing.B) {
98+
for i := 0; i < b.N; i++ {
99+
metrics.QueryTotalCounter.WithLabelValues("127.0.0.1:4000", pnet.ComQuery.String()).Inc()
100+
}
101+
}

0 commit comments

Comments
 (0)