diff --git a/config/config.go b/config/config.go index 2c8336ef05045..a33ee70ee4f0b 100644 --- a/config/config.go +++ b/config/config.go @@ -299,6 +299,7 @@ type Performance struct { TCPKeepAlive bool `toml:"tcp-keep-alive" json:"tcp-keep-alive"` CrossJoin bool `toml:"cross-join" json:"cross-join"` RunAutoAnalyze bool `toml:"run-auto-analyze" json:"run-auto-analyze"` + PProfSQLCPU bool `toml:"pprof-sql-cpu" json:"pprof-sql-cpu"` } // PlanCache is the PlanCache section of the config. diff --git a/server/conn.go b/server/conn.go index e7fdd676450c6..30b539b3e7657 100644 --- a/server/conn.go +++ b/server/conn.go @@ -43,6 +43,7 @@ import ( "io" "net" "runtime" + "runtime/pprof" "strconv" "strings" "sync/atomic" @@ -51,6 +52,7 @@ import ( "github.com/opentracing/opentracing-go" "github.com/pingcap/errors" "github.com/pingcap/failpoint" + "github.com/pingcap/parser" "github.com/pingcap/parser/auth" "github.com/pingcap/parser/mysql" "github.com/pingcap/parser/terror" @@ -60,6 +62,7 @@ import ( "github.com/pingcap/tidb/plugin" "github.com/pingcap/tidb/sessionctx" "github.com/pingcap/tidb/sessionctx/variable" + "github.com/pingcap/tidb/util" "github.com/pingcap/tidb/util/arena" "github.com/pingcap/tidb/util/chunk" "github.com/pingcap/tidb/util/hack" @@ -804,6 +807,12 @@ func (cc *clientConn) dispatch(ctx context.Context, data []byte) error { cc.lastPacket = data cmd := data[0] data = data[1:] + if util.EnablePProfSQLCPU.Load() { + defer pprof.SetGoroutineLabels(ctx) + lastSQL := getLastStmtInConn{cc}.String() + ctx = pprof.WithLabels(ctx, pprof.Labels("sql", parser.Normalize(lastSQL))) + pprof.SetGoroutineLabels(ctx) + } token := cc.server.getToken() defer func() { // if handleChangeUser failed, cc.ctx may be nil diff --git a/tidb-server/main.go b/tidb-server/main.go index 9b56415605a9d..6a05067990e3c 100644 --- a/tidb-server/main.go +++ b/tidb-server/main.go @@ -51,6 +51,7 @@ import ( "github.com/pingcap/tidb/store/mockstore" "github.com/pingcap/tidb/store/tikv" "github.com/pingcap/tidb/store/tikv/gcworker" + "github.com/pingcap/tidb/util" "github.com/pingcap/tidb/util/domainutil" "github.com/pingcap/tidb/util/logutil" "github.com/pingcap/tidb/util/memory" @@ -394,7 +395,7 @@ func loadConfig() string { var hotReloadConfigItems = []string{"Performance.MaxProcs", "Performance.MaxMemory", "Performance.CrossJoin", "Performance.FeedbackProbability", "Performance.QueryFeedbackLimit", "Performance.PseudoEstimateRatio", "OOMUseTmpStorage", "OOMAction", "MemQuotaQuery", "StmtSummary.MaxStmtCount", "StmtSummary.MaxSQLLength", "Log.QueryLogMaxLen", - "TiKVClient.EnableChunkRPC", "TiKVClient.StoreLimit"} + "TiKVClient.EnableChunkRPC", "TiKVClient.StoreLimit", "Performance.PProfSQLCPU"} func reloadConfig(nc, c *config.Config) { // Just a part of config items need to be reload explicitly. @@ -417,6 +418,9 @@ func reloadConfig(nc, c *config.Config) { if nc.Performance.PseudoEstimateRatio != c.Performance.PseudoEstimateRatio { statistics.RatioOfPseudoEstimate.Store(nc.Performance.PseudoEstimateRatio) } + if nc.Performance.PProfSQLCPU != c.Performance.PProfSQLCPU { + util.EnablePProfSQLCPU.Store(nc.Performance.PProfSQLCPU) + } if nc.TiKVClient.StoreLimit != c.TiKVClient.StoreLimit { storeutil.StoreLimit.Store(nc.TiKVClient.StoreLimit) } @@ -536,6 +540,7 @@ func setGlobalVars() { statistics.FeedbackProbability.Store(cfg.Performance.FeedbackProbability) handle.MaxQueryFeedbackCount.Store(int64(cfg.Performance.QueryFeedbackLimit)) statistics.RatioOfPseudoEstimate.Store(cfg.Performance.PseudoEstimateRatio) + util.EnablePProfSQLCPU.Store(cfg.Performance.PProfSQLCPU) ddl.RunWorker = cfg.RunDDL if cfg.SplitTable { atomic.StoreUint32(&ddl.EnableSplitTableRegion, 1) diff --git a/util/misc.go b/util/misc.go index a1e39129b6de2..91b060a810983 100644 --- a/util/misc.go +++ b/util/misc.go @@ -28,6 +28,7 @@ import ( "github.com/pingcap/parser/mysql" "github.com/pingcap/parser/terror" "github.com/pingcap/tidb/util/logutil" + "github.com/uber-go/atomic" "go.uber.org/zap" ) @@ -40,6 +41,9 @@ const ( GCTimeFormat = "20060102-15:04:05 -0700" ) +// EnablePProfSQLCPU control whether collect pprof cpu in SQL level. +var EnablePProfSQLCPU = atomic.NewBool(false) + // RunWithRetry will run the f with backoff and retry. // retryCnt: Max retry count // backoff: When run f failed, it will sleep backoff * triedCount time.Millisecond.