Skip to content

Commit 7e6ce64

Browse files
authored
types: add a interface to eval the memory cost of datum array (pingcap#14185)
1 parent ef7adeb commit 7e6ce64

File tree

2 files changed

+48
-0
lines changed

2 files changed

+48
-0
lines changed

types/datum.go

+28
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import (
2121
"strings"
2222
"time"
2323
"unicode/utf8"
24+
"unsafe"
2425

2526
"github.com/pingcap/errors"
2627
"github.com/pingcap/parser/charset"
@@ -2057,3 +2058,30 @@ func ChangeReverseResultByUpperLowerBound(
20572058
}
20582059
return d, nil
20592060
}
2061+
2062+
const (
2063+
sizeOfEmptyDatum = int(unsafe.Sizeof(Datum{}))
2064+
sizeOfMysqlTime = int(unsafe.Sizeof(Time{}))
2065+
sizeOfMyDecimal = MyDecimalStructSize
2066+
)
2067+
2068+
// EstimatedMemUsage returns the estimated bytes consumed of a one-dimensional
2069+
// or two-dimensional datum array.
2070+
func EstimatedMemUsage(array []Datum, numOfRows int) int64 {
2071+
if numOfRows == 0 {
2072+
return 0
2073+
}
2074+
var bytesConsumed int
2075+
for _, d := range array {
2076+
switch d.Kind() {
2077+
case KindMysqlDecimal:
2078+
bytesConsumed += sizeOfMyDecimal
2079+
case KindMysqlTime:
2080+
bytesConsumed += sizeOfMysqlTime
2081+
default:
2082+
bytesConsumed += len(d.b)
2083+
}
2084+
}
2085+
bytesConsumed += len(array) * sizeOfEmptyDatum
2086+
return int64(bytesConsumed * numOfRows)
2087+
}

types/datum_test.go

+20
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import (
2525
"github.com/pingcap/parser/mysql"
2626
"github.com/pingcap/tidb/sessionctx/stmtctx"
2727
"github.com/pingcap/tidb/types/json"
28+
"github.com/pingcap/tidb/util/hack"
2829
)
2930

3031
var _ = Suite(&testDatumSuite{})
@@ -396,6 +397,25 @@ func newRetTypeWithFlenDecimal(tp byte, flen int, decimal int) *FieldType {
396397
}
397398
}
398399

400+
func (ts *testDatumSuite) TestEstimatedMemUsage(c *C) {
401+
b := []byte{'a', 'b', 'c', 'd'}
402+
enum := Enum{Name: "a", Value: 1}
403+
datumArray := []Datum{
404+
NewIntDatum(1),
405+
NewFloat64Datum(1.0),
406+
NewFloat32Datum(1.0),
407+
NewStringDatum(string(b)),
408+
NewBytesDatum(b),
409+
NewDecimalDatum(newMyDecimal("1234.1234", c)),
410+
NewMysqlEnumDatum(enum),
411+
}
412+
bytesConsumed := 10 * (len(datumArray)*sizeOfEmptyDatum +
413+
sizeOfMyDecimal +
414+
len(b)*2 +
415+
len(hack.Slice(enum.Name)))
416+
c.Assert(int(EstimatedMemUsage(datumArray, 10)), Equals, bytesConsumed)
417+
}
418+
399419
func (ts *testDatumSuite) TestChangeReverseResultByUpperLowerBound(c *C) {
400420
sc := new(stmtctx.StatementContext)
401421
sc.IgnoreTruncate = true

0 commit comments

Comments
 (0)