Skip to content

Commit

Permalink
planner: PhysicalPlan memory trace 8 (#38162)
Browse files Browse the repository at this point in the history
ref #37632
  • Loading branch information
fzzf678 authored Sep 27, 2022
1 parent 7b3c503 commit c5a28bf
Show file tree
Hide file tree
Showing 6 changed files with 139 additions and 0 deletions.
21 changes: 21 additions & 0 deletions planner/core/common_plans.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ import (
"github.com/pingcap/tidb/util/hint"
"github.com/pingcap/tidb/util/memory"
"github.com/pingcap/tidb/util/plancodec"
"github.com/pingcap/tidb/util/size"
"github.com/pingcap/tidb/util/texttree"
"github.com/pingcap/tipb/go-tipb"
)
Expand Down Expand Up @@ -280,6 +281,16 @@ type Simple struct {
StaleTxnStartTS uint64
}

// MemoryUsage return the memory usage of Simple
func (s *Simple) MemoryUsage() (sum int64) {
if s == nil {
return
}

sum = s.baseSchemaProducer.MemoryUsage() + size.SizeOfInterface + size.SizeOfBool + size.SizeOfUint64
return
}

// PhysicalSimpleWrapper is a wrapper of `Simple` to implement physical plan interface.
//
// Used for simple statements executing in coprocessor.
Expand All @@ -288,6 +299,16 @@ type PhysicalSimpleWrapper struct {
Inner Simple
}

// MemoryUsage return the memory usage of PhysicalSimpleWrapper
func (p *PhysicalSimpleWrapper) MemoryUsage() (sum int64) {
if p == nil {
return
}

sum = p.basePhysicalPlan.MemoryUsage() + p.Inner.MemoryUsage()
return
}

// InsertGeneratedColumns is for completing generated columns in Insert.
// We resolve generation expressions in plan, and eval those in executor.
type InsertGeneratedColumns struct {
Expand Down
24 changes: 24 additions & 0 deletions planner/core/fragment.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ package core
import (
"context"
"time"
"unsafe"

"github.com/pingcap/errors"
"github.com/pingcap/tidb/distsql"
Expand All @@ -29,6 +30,7 @@ import (
"github.com/pingcap/tidb/types"
"github.com/pingcap/tidb/util/logutil"
"github.com/pingcap/tidb/util/ranger"
"github.com/pingcap/tidb/util/size"
"github.com/pingcap/tipb/go-tipb"
"go.uber.org/zap"
"golang.org/x/exp/slices"
Expand All @@ -49,6 +51,28 @@ type Fragment struct {
singleton bool // indicates if this is a task running on a single node.
}

const emptyFragmentSize = int64(unsafe.Sizeof(Fragment{}))

// MemoryUsage return the memory usage of Fragment
func (f *Fragment) MemoryUsage() (sum int64) {
if f == nil {
return
}

sum = emptyFragmentSize + int64(cap(f.ExchangeReceivers))*size.SizeOfPointer
if f.TableScan != nil {
sum += f.TableScan.MemoryUsage()
}
if f.ExchangeSender != nil {
sum += f.ExchangeSender.MemoryUsage()
}

for _, receiver := range f.ExchangeReceivers {
sum += receiver.MemoryUsage()
}
return
}

type tasksAndFrags struct {
tasks []*kv.MPPTask
frags []*Fragment
Expand Down
63 changes: 63 additions & 0 deletions planner/core/physical_plans.go
Original file line number Diff line number Diff line change
Expand Up @@ -756,6 +756,17 @@ type PhysicalMemTable struct {
QueryTimeRange QueryTimeRange
}

// MemoryUsage return the memory usage of PhysicalMemTable
func (p *PhysicalMemTable) MemoryUsage() (sum int64) {
if p == nil {
return
}

sum = p.physicalSchemaProducer.MemoryUsage() + p.DBName.MemoryUsage() + size.SizeOfPointer + size.SizeOfSlice +
int64(cap(p.Columns))*size.SizeOfPointer + size.SizeOfInterface + p.QueryTimeRange.MemoryUsage()
return
}

// PhysicalTableScan represents a table scan plan.
type PhysicalTableScan struct {
physicalSchemaProducer
Expand Down Expand Up @@ -1445,6 +1456,21 @@ func (p *PhysicalExchangeReceiver) GetExchangeSender() *PhysicalExchangeSender {
return p.children[0].(*PhysicalExchangeSender)
}

const emptyMPPTaskSize = int64(unsafe.Sizeof(mppTask{}))

// MemoryUsage return the memory usage of PhysicalExchangeReceiver
func (p *PhysicalExchangeReceiver) MemoryUsage() (sum int64) {
if p == nil {
return
}

sum = p.basePhysicalPlan.MemoryUsage() + size.SizeOfSlice*2 + int64(cap(p.Tasks)+cap(p.frags))*size.SizeOfPointer
for _, frag := range p.frags {
sum += frag.MemoryUsage()
}
return
}

// PhysicalExchangeSender dispatches data to upstream tasks. That means push mode processing,
type PhysicalExchangeSender struct {
basePhysicalPlan
Expand All @@ -1469,6 +1495,20 @@ func (p *PhysicalExchangeSender) Clone() (PhysicalPlan, error) {
return np, nil
}

// MemoryUsage return the memory usage of PhysicalExchangeSender
func (p *PhysicalExchangeSender) MemoryUsage() (sum int64) {
if p == nil {
return
}

sum = p.basePhysicalPlan.MemoryUsage() + size.SizeOfSlice*3 + size.SizeOfInt32 +
int64(cap(p.TargetTasks)+cap(p.HashCols)+cap(p.Tasks))*size.SizeOfPointer
for _, hCol := range p.HashCols {
sum += hCol.MemoryUsage()
}
return
}

// Clone implements PhysicalPlan interface.
func (p *PhysicalMergeJoin) Clone() (PhysicalPlan, error) {
cloned := new(PhysicalMergeJoin)
Expand All @@ -1492,6 +1532,29 @@ type PhysicalLock struct {
TblID2PhysTblIDCol map[int64]*expression.Column
}

// MemoryUsage return the memory usage of PhysicalLock
func (pl *PhysicalLock) MemoryUsage() (sum int64) {
if pl == nil {
return
}

sum = pl.basePhysicalPlan.MemoryUsage() + size.SizeOfPointer + size.SizeOfMap*2
if pl.Lock != nil {
sum += int64(unsafe.Sizeof(ast.SelectLockInfo{}))
}

for _, vals := range pl.TblID2Handle {
sum += size.SizeOfInt64 + size.SizeOfSlice + int64(cap(vals))*size.SizeOfInterface
for _, val := range vals {
sum += val.MemoryUsage()
}
}
for _, val := range pl.TblID2PhysTblIDCol {
sum += size.SizeOfInt64 + size.SizeOfPointer + val.MemoryUsage()
}
return
}

// PhysicalLimit is the physical operator of Limit.
type PhysicalLimit struct {
physicalSchemaProducer
Expand Down
12 changes: 12 additions & 0 deletions planner/core/planbuilder.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import (
"strconv"
"strings"
"time"
"unsafe"

"github.com/pingcap/errors"
"github.com/pingcap/tidb/bindinfo"
Expand Down Expand Up @@ -173,6 +174,17 @@ func (tr *QueryTimeRange) Condition() string {
return fmt.Sprintf("where time>='%s' and time<='%s'", tr.From.Format(MetricTableTimeFormat), tr.To.Format(MetricTableTimeFormat))
}

const emptyQueryTimeRangeSize = int64(unsafe.Sizeof(QueryTimeRange{}))

// MemoryUsage return the memory usage of QueryTimeRange
func (tr *QueryTimeRange) MemoryUsage() (sum int64) {
if tr == nil {
return
}

return emptyQueryTimeRangeSize
}

func tableNames2HintTableInfo(ctx sessionctx.Context, hintName string, hintTables []ast.HintTable, p *hint.BlockHintProcessor, currentOffset int) []hintTableInfo {
if len(hintTables) == 0 {
return nil
Expand Down
13 changes: 13 additions & 0 deletions planner/core/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,19 @@ func (s *baseSchemaProducer) setSchemaAndNames(schema *expression.Schema, names
s.names = names
}

// MemoryUsage return the memory usage of baseSchemaProducer
func (s *baseSchemaProducer) MemoryUsage() (sum int64) {
if s == nil {
return
}

sum = size.SizeOfPointer + size.SizeOfSlice + int64(cap(s.names))*size.SizeOfPointer + s.basePlan.MemoryUsage()
if s.schema != nil {
sum += s.schema.MemoryUsage()
}
return
}

// Schema implements the Plan.Schema interface.
func (p *LogicalMaxOneRow) Schema() *expression.Schema {
s := p.Children()[0].Schema().Clone()
Expand Down
6 changes: 6 additions & 0 deletions util/size/size.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,4 +69,10 @@ const (

// SizeOfFunc is the memory each function occupied
SizeOfFunc = int64(unsafe.Sizeof(*new(func())))

// SizeOfInt64 is the memory each int64 occupied
SizeOfInt64 = int64(unsafe.Sizeof(*new(int64)))

// SizeOfMap is the memory each map itsel occupied
SizeOfMap = int64(unsafe.Sizeof(*new(map[int]int)))
)

0 comments on commit c5a28bf

Please sign in to comment.