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

resource_control: calibrate resource support sysbench #42695

Merged
merged 5 commits into from
Apr 14, 2023
Merged
Show file tree
Hide file tree
Changes from all 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
5 changes: 4 additions & 1 deletion executor/builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -839,7 +839,10 @@ func (b *executorBuilder) buildSimple(v *plannercore.Simple) Executor {
}
}
case *ast.CalibrateResourceStmt:
return b.buildCalibrateResource(v.Schema())
return &calibrateResourceExec{
baseExecutor: newBaseExecutor(b.ctx, v.Schema(), 0),
workloadType: s.Tp,
}
case *ast.LoadDataActionStmt:
return &LoadDataActionExec{
baseExecutor: newBaseExecutor(b.ctx, nil, 0),
Expand Down
63 changes: 39 additions & 24 deletions executor/calibrate_resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,40 +21,57 @@ import (

"github.com/docker/go-units"
"github.com/pingcap/errors"
"github.com/pingcap/tidb/expression"
"github.com/pingcap/tidb/kv"
"github.com/pingcap/tidb/parser/ast"
"github.com/pingcap/tidb/util/chunk"
"github.com/pingcap/tidb/util/sqlexec"
)

const (
// the workload name of TPC-C
workloadTpcc = "tpcc"
// the default workload to calculate the RU capacity.
defaultWorkload = workloadTpcc
)

// workloadBaseRUCostMap contains the base resource cost rate per 1 kv cpu within 1 second,
// the data is calculated from benchmark result, these data might not be very accurate,
// but is enough here because the maximum RU capacity is depend on both the cluster and
// but is enough here because the maximum RU capacity is depended on both the cluster and
// the workload.
var workloadBaseRUCostMap = map[string]*baseResourceCost{
workloadTpcc: {
var workloadBaseRUCostMap = map[ast.CalibrateResourceType]*baseResourceCost{
ast.TPCC: {
tidbCPU: 0.6,
kvCPU: 0.15,
readBytes: units.MiB / 2,
writeBytes: units.MiB,
readReqCount: 300,
writeReqCount: 1750,
},
ast.OLTPREADWRITE: {
tidbCPU: 1.25,
kvCPU: 0.35,
readBytes: units.MiB * 4.25,
writeBytes: units.MiB / 3,
readReqCount: 1600,
writeReqCount: 1400,
},
ast.OLTPREADONLY: {
tidbCPU: 2,
kvCPU: 0.52,
readBytes: units.MiB * 28,
writeBytes: 0,
readReqCount: 4500,
writeReqCount: 0,
},
ast.OLTPWRITEONLY: {
tidbCPU: 1,
kvCPU: 0,
readBytes: 0,
writeBytes: units.MiB,
readReqCount: 0,
writeReqCount: 3550,
},
}

// the resource cost rate of a specified workload per 1 tikv cpu
type baseResourceCost struct {
// the average tikv cpu time, this is used to calculate whether tikv cpu
// or tidb cpu is the performance bottle neck.
tidbCPU float64
// the kv CPU time for calculate RU, it's smaller than the actually cpu usage.
// the kv CPU time for calculate RU, it's smaller than the actual cpu usage.
kvCPU float64
// the read bytes rate per 1 tikv cpu.
readBytes uint64
Expand All @@ -66,15 +83,11 @@ type baseResourceCost struct {
writeReqCount uint64
}

func (b *executorBuilder) buildCalibrateResource(schema *expression.Schema) Executor {
return &calibrateResourceExec{
baseExecutor: newBaseExecutor(b.ctx, schema, 0),
}
}

type calibrateResourceExec struct {
baseExecutor
done bool

workloadType ast.CalibrateResourceType
done bool
}

func (e *calibrateResourceExec) Next(ctx context.Context, req *chunk.Chunk) error {
Expand Down Expand Up @@ -102,11 +115,13 @@ func (e *calibrateResourceExec) Next(ctx context.Context, req *chunk.Chunk) erro
return err
}

// we only support TPC-C currently, will support more in the future.
workload := defaultWorkload
baseCost, ok := workloadBaseRUCostMap[workload]
// The default workload to calculate the RU capacity.
if e.workloadType == ast.WorkloadNone {
e.workloadType = ast.TPCC
}
baseCost, ok := workloadBaseRUCostMap[e.workloadType]
if !ok {
return errors.Errorf("unknown workload '%s'", workload)
return errors.Errorf("unknown workload '%T'", e.workloadType)
}

if totalTiDBCPU/baseCost.tidbCPU < totalKVCPUQuota {
Expand All @@ -132,7 +147,7 @@ type ruConfig struct {
}

func getRUSettings(ctx context.Context, exec sqlexec.RestrictedSQLExecutor) (*ruConfig, error) {
rows, fields, err := exec.ExecRestrictedSQL(ctx, []sqlexec.OptionFuncAlias{sqlexec.ExecOptionUseCurSession}, "SHOW CONFIG WHERE TYPE = 'pd' AND name like 'controller.request-unit.%'")
rows, fields, err := exec.ExecRestrictedSQL(ctx, []sqlexec.OptionFuncAlias{sqlexec.ExecOptionUseCurSession}, "SHOW CONFIG WHERE TYPE = 'pd' AND name like 'controller.request-unit.%'")
if err != nil {
return nil, errors.Trace(err)
}
Expand Down
6 changes: 5 additions & 1 deletion executor/calibrate_resource_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ func TestCalibrateResource(t *testing.T) {
return items
}

// empty requet-unit config error
// empty request-unit config error
rs, err := tk.Exec("CALIBRATE RESOURCE")
require.NoError(t, err)
require.NotNil(t, rs)
Expand Down Expand Up @@ -96,6 +96,10 @@ func TestCalibrateResource(t *testing.T) {
return fpName == fpname
})
tk.MustQueryWithContext(ctx, "CALIBRATE RESOURCE").Check(testkit.Rows("68569"))
tk.MustQueryWithContext(ctx, "CALIBRATE RESOURCE WORKLOAD TPCC").Check(testkit.Rows("68569"))
tk.MustQueryWithContext(ctx, "CALIBRATE RESOURCE WORKLOAD OLTP_READ_WRITE").Check(testkit.Rows("53026"))
tk.MustQueryWithContext(ctx, "CALIBRATE RESOURCE WORKLOAD OLTP_READ_ONLY").Check(testkit.Rows("31463"))
tk.MustQueryWithContext(ctx, "CALIBRATE RESOURCE WORKLOAD OLTP_WRITE_ONLY").Check(testkit.Rows("109776"))

// change total tidb cpu to less than tikv_cpu_quota
mockData["tidb_server_maxprocs"] = [][]types.Datum{
Expand Down
4 changes: 2 additions & 2 deletions metrics/grafana/tidb_resource_control.json
Original file line number Diff line number Diff line change
Expand Up @@ -2164,7 +2164,7 @@
"timeFrom": null,
"timeRegions": [],
"timeShift": null,
"title": "Seccessful KV Request Wait Duration",
"title": "Successful KV Request Wait Duration",
"tooltip": {
"msResolution": true,
"shared": true,
Expand Down Expand Up @@ -2280,7 +2280,7 @@
"timeFrom": null,
"timeRegions": [],
"timeShift": null,
"title": "Seccessful KV Request Count",
"title": "Successful KV Request Count",
"tooltip": {
"msResolution": true,
"shared": true,
Expand Down
30 changes: 30 additions & 0 deletions parser/ast/misc.go
Original file line number Diff line number Diff line change
Expand Up @@ -3721,14 +3721,44 @@ func (n *SetResourceGroupStmt) Accept(v Visitor) (Node, bool) {
return v.Leave(n)
}

// CalibrateResourceType is the type for CalibrateResource statement.
type CalibrateResourceType int

// calibrate resource [ workload < TPCC | OLTP_READ_WRITE | OLTP_READ_ONLY | OLTP_WRITE_ONLY> ]
const (
WorkloadNone CalibrateResourceType = iota
TPCC
OLTPREADWRITE
OLTPREADONLY
OLTPWRITEONLY
)

func (n CalibrateResourceType) Restore(ctx *format.RestoreCtx) error {
switch n {
case TPCC:
ctx.WriteKeyWord(" WORKLOAD TPCC")
case OLTPREADWRITE:
ctx.WriteKeyWord(" WORKLOAD OLTP_READ_WRITE")
case OLTPREADONLY:
ctx.WriteKeyWord(" WORKLOAD OLTP_READ_ONLY")
case OLTPWRITEONLY:
ctx.WriteKeyWord(" WORKLOAD OLTP_WRITE_ONLY")
}
return nil
}

// CalibrateResourceStmt is a statement to fetch the cluster RU capacity
type CalibrateResourceStmt struct {
stmtNode
Tp CalibrateResourceType
}

// Restore implements Node interface.
func (n *CalibrateResourceStmt) Restore(ctx *format.RestoreCtx) error {
ctx.WriteKeyWord("CALIBRATE RESOURCE")
if err := n.Tp.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while restore CalibrateResourceStmt.CalibrateResourceType")
}
return nil
}

Expand Down
5 changes: 5 additions & 0 deletions parser/misc.go
Original file line number Diff line number Diff line change
Expand Up @@ -539,6 +539,9 @@ var tokenMap = map[string]int{
"OF": of,
"OFF": off,
"OFFSET": offset,
"OLTP_READ_ONLY": oltpReadOnly,
"OLTP_READ_WRITE": oltpReadWrite,
"OLTP_WRITE_ONLY": oltpWriteOnly,
"ON_DUPLICATE": onDuplicate,
"ON": on,
"ONLINE": online,
Expand Down Expand Up @@ -785,6 +788,7 @@ var tokenMap = map[string]int{
"TOKUDB_ZSTD": tokudbZstd,
"TOP": top,
"TOPN": topn,
"TPCC": tpcc,
"TRACE": trace,
"TRADITIONAL": traditional,
"TRAILING": trailing,
Expand Down Expand Up @@ -844,6 +848,7 @@ var tokenMap = map[string]int{
"WITH": with,
"WITHOUT": without,
"WRITE": write,
"WORKLOAD": workload,
"X509": x509,
"XOR": xor,
"YEAR_MONTH": yearMonth,
Expand Down
Loading