Skip to content

Commit

Permalink
expression: go generate vectorized addtime functions (pingcap#12224)
Browse files Browse the repository at this point in the history
  • Loading branch information
SunRunAway authored and sre-bot committed Sep 26, 2019
1 parent 2dc6264 commit 35e308f
Show file tree
Hide file tree
Showing 14 changed files with 1,393 additions and 111 deletions.
1 change: 1 addition & 0 deletions .codecov.yml
Original file line number Diff line number Diff line change
Expand Up @@ -42,4 +42,5 @@ ignore:
- "ddl/testutil/.*"
- "executor/seqtest/.*"
- "metrics/.*"
- "expression/generator/.*"

63 changes: 45 additions & 18 deletions expression/bench_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -449,11 +449,12 @@ func eType2FieldType(eType types.EvalType) *types.FieldType {
}

func genVecExprBenchCase(ctx sessionctx.Context, funcName string, testCase vecExprBenchCase) (expr Expression, fts []*types.FieldType, input *chunk.Chunk, output *chunk.Chunk) {
fts = testCase.childrenFieldTypes
if fts == nil {
fts = make([]*types.FieldType, len(testCase.childrenTypes))
for i, eType := range testCase.childrenTypes {
fts[i] = eType2FieldType(eType)
fts = make([]*types.FieldType, len(testCase.childrenTypes))
for i := range fts {
if i < len(testCase.childrenFieldTypes) && testCase.childrenFieldTypes[i] != nil {
fts[i] = testCase.childrenFieldTypes[i]
} else {
fts[i] = eType2FieldType(testCase.childrenTypes[i])
}
}
cols := make([]Expression, len(testCase.childrenTypes))
Expand Down Expand Up @@ -580,11 +581,12 @@ func benchmarkVectorizedEvalOneVec(b *testing.B, vecExprCases vecExprBenchCases)

func genVecBuiltinFuncBenchCase(ctx sessionctx.Context, funcName string, testCase vecExprBenchCase) (baseFunc builtinFunc, fts []*types.FieldType, input *chunk.Chunk, result *chunk.Column) {
childrenNumber := len(testCase.childrenTypes)
fts = testCase.childrenFieldTypes
if fts == nil {
fts = make([]*types.FieldType, childrenNumber)
for i, eType := range testCase.childrenTypes {
fts[i] = eType2FieldType(eType)
fts = make([]*types.FieldType, childrenNumber)
for i := range fts {
if i < len(testCase.childrenFieldTypes) && testCase.childrenFieldTypes[i] != nil {
fts[i] = testCase.childrenFieldTypes[i]
} else {
fts[i] = eType2FieldType(testCase.childrenTypes[i])
}
}
cols := make([]Expression, childrenNumber)
Expand Down Expand Up @@ -622,9 +624,18 @@ func genVecBuiltinFuncBenchCase(ctx sessionctx.Context, funcName string, testCas
panic(err)
}
result = chunk.NewColumn(eType2FieldType(testCase.retEvalType), 1024)
// Mess up the output to make sure vecEvalXXX to call ResizeXXX/ReserveXXX itself.
result.AppendNull()
return baseFunc, fts, input, result
}

// a hack way to calculate length of a chunk.Column.
func getColumnLen(col *chunk.Column, eType types.EvalType) int {
chk := chunk.New([]*types.FieldType{eType2FieldType(eType)}, 1024, 1024)
chk.SetCol(0, col)
return chk.NumRows()
}

// testVectorizedBuiltinFunc is used to verify that the vectorized
// expression is evaluated correctly
func testVectorizedBuiltinFunc(c *C, vecExprCases vecExprBenchCases) {
Expand All @@ -645,8 +656,10 @@ func testVectorizedBuiltinFunc(c *C, vecExprCases vecExprBenchCases) {
if !testAll && testFunc[baseFuncName] != true {
continue
}
// do not forget to implement the vectorized method.
c.Assert(baseFunc.vectorized(), IsTrue, Commentf("func: %v", baseFuncName))
commentf := func(row int) CommentInterface {
return Commentf("case %+v, row: %v, rowData: %v", testCase, row, input.GetRow(row).GetDatumRow(fts))
return Commentf("func: %v, case %+v, row: %v, rowData: %v", baseFuncName, testCase, row, input.GetRow(row).GetDatumRow(fts))
}
it := chunk.NewIterator4Chunk(input)
i := 0
Expand All @@ -655,12 +668,14 @@ func testVectorizedBuiltinFunc(c *C, vecExprCases vecExprBenchCases) {
case types.ETInt:
err := baseFunc.vecEvalInt(input, output)
c.Assert(err, IsNil)
// do not forget to call ResizeXXX/ReserveXXX
c.Assert(getColumnLen(output, testCase.retEvalType), Equals, input.NumRows())
vecWarnCnt = ctx.GetSessionVars().StmtCtx.WarningCount()
i64s := output.Int64s()
for row := it.Begin(); row != it.End(); row = it.Next() {
val, isNull, err := baseFunc.evalInt(row)
c.Assert(err, IsNil)
c.Assert(isNull, Equals, output.IsNull(i))
c.Assert(isNull, Equals, output.IsNull(i), commentf(i))
if !isNull {
c.Assert(val, Equals, i64s[i], commentf(i))
}
Expand All @@ -669,12 +684,14 @@ func testVectorizedBuiltinFunc(c *C, vecExprCases vecExprBenchCases) {
case types.ETReal:
err := baseFunc.vecEvalReal(input, output)
c.Assert(err, IsNil)
// do not forget to call ResizeXXX/ReserveXXX
c.Assert(getColumnLen(output, testCase.retEvalType), Equals, input.NumRows())
vecWarnCnt = ctx.GetSessionVars().StmtCtx.WarningCount()
f64s := output.Float64s()
for row := it.Begin(); row != it.End(); row = it.Next() {
val, isNull, err := baseFunc.evalReal(row)
c.Assert(err, IsNil)
c.Assert(isNull, Equals, output.IsNull(i))
c.Assert(isNull, Equals, output.IsNull(i), commentf(i))
if !isNull {
c.Assert(val, Equals, f64s[i], commentf(i))
}
Expand All @@ -683,12 +700,14 @@ func testVectorizedBuiltinFunc(c *C, vecExprCases vecExprBenchCases) {
case types.ETDecimal:
err := baseFunc.vecEvalDecimal(input, output)
c.Assert(err, IsNil)
// do not forget to call ResizeXXX/ReserveXXX
c.Assert(getColumnLen(output, testCase.retEvalType), Equals, input.NumRows())
vecWarnCnt = ctx.GetSessionVars().StmtCtx.WarningCount()
d64s := output.Decimals()
for row := it.Begin(); row != it.End(); row = it.Next() {
val, isNull, err := baseFunc.evalDecimal(row)
c.Assert(err, IsNil)
c.Assert(isNull, Equals, output.IsNull(i))
c.Assert(isNull, Equals, output.IsNull(i), commentf(i))
if !isNull {
c.Assert(*val, Equals, d64s[i], commentf(i))
}
Expand All @@ -697,12 +716,14 @@ func testVectorizedBuiltinFunc(c *C, vecExprCases vecExprBenchCases) {
case types.ETDatetime, types.ETTimestamp:
err := baseFunc.vecEvalTime(input, output)
c.Assert(err, IsNil)
// do not forget to call ResizeXXX/ReserveXXX
c.Assert(getColumnLen(output, testCase.retEvalType), Equals, input.NumRows())
vecWarnCnt = ctx.GetSessionVars().StmtCtx.WarningCount()
t64s := output.Times()
for row := it.Begin(); row != it.End(); row = it.Next() {
val, isNull, err := baseFunc.evalTime(row)
c.Assert(err, IsNil)
c.Assert(isNull, Equals, output.IsNull(i))
c.Assert(isNull, Equals, output.IsNull(i), commentf(i))
if !isNull {
c.Assert(val, Equals, t64s[i], commentf(i))
}
Expand All @@ -711,12 +732,14 @@ func testVectorizedBuiltinFunc(c *C, vecExprCases vecExprBenchCases) {
case types.ETDuration:
err := baseFunc.vecEvalDuration(input, output)
c.Assert(err, IsNil)
// do not forget to call ResizeXXX/ReserveXXX
c.Assert(getColumnLen(output, testCase.retEvalType), Equals, input.NumRows())
vecWarnCnt = ctx.GetSessionVars().StmtCtx.WarningCount()
d64s := output.GoDurations()
for row := it.Begin(); row != it.End(); row = it.Next() {
val, isNull, err := baseFunc.evalDuration(row)
c.Assert(err, IsNil)
c.Assert(isNull, Equals, output.IsNull(i))
c.Assert(isNull, Equals, output.IsNull(i), commentf(i))
if !isNull {
c.Assert(val.Duration, Equals, d64s[i], commentf(i))
}
Expand All @@ -725,11 +748,13 @@ func testVectorizedBuiltinFunc(c *C, vecExprCases vecExprBenchCases) {
case types.ETJson:
err := baseFunc.vecEvalJSON(input, output)
c.Assert(err, IsNil)
// do not forget to call ResizeXXX/ReserveXXX
c.Assert(getColumnLen(output, testCase.retEvalType), Equals, input.NumRows())
vecWarnCnt = ctx.GetSessionVars().StmtCtx.WarningCount()
for row := it.Begin(); row != it.End(); row = it.Next() {
val, isNull, err := baseFunc.evalJSON(row)
c.Assert(err, IsNil)
c.Assert(isNull, Equals, output.IsNull(i))
c.Assert(isNull, Equals, output.IsNull(i), commentf(i))
if !isNull {
var cmp int
cmp = json.CompareBinary(val, output.GetJSON(i))
Expand All @@ -740,11 +765,13 @@ func testVectorizedBuiltinFunc(c *C, vecExprCases vecExprBenchCases) {
case types.ETString:
err := baseFunc.vecEvalString(input, output)
c.Assert(err, IsNil)
// do not forget to call ResizeXXX/ReserveXXX
c.Assert(getColumnLen(output, testCase.retEvalType), Equals, input.NumRows())
vecWarnCnt = ctx.GetSessionVars().StmtCtx.WarningCount()
for row := it.Begin(); row != it.End(); row = it.Next() {
val, isNull, err := baseFunc.evalString(row)
c.Assert(err, IsNil)
c.Assert(isNull, Equals, output.IsNull(i))
c.Assert(isNull, Equals, output.IsNull(i), commentf(i))
if !isNull {
c.Assert(val, Equals, output.GetString(i), commentf(i))
}
Expand Down
1 change: 1 addition & 0 deletions expression/builtin.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
// limitations under the License.

//go:generate go run generator/control_vec.go
//go:generate go run generator/time_vec.go

package expression

Expand Down
31 changes: 29 additions & 2 deletions expression/builtin_cast_vec.go
Original file line number Diff line number Diff line change
Expand Up @@ -362,11 +362,38 @@ func (b *builtinCastRealAsDurationSig) vecEvalDuration(input *chunk.Chunk, resul
}

func (b *builtinCastTimeAsDurationSig) vectorized() bool {
return false
return true
}

func (b *builtinCastTimeAsDurationSig) vecEvalDuration(input *chunk.Chunk, result *chunk.Column) error {
return errors.Errorf("not implemented")
n := input.NumRows()
arg0, err := b.bufAllocator.get(types.ETDatetime, n)
if err != nil {
return err
}
defer b.bufAllocator.put(arg0)
if err := b.args[0].VecEvalTime(b.ctx, input, arg0); err != nil {
return err
}
arg0s := arg0.Times()
result.ResizeGoDuration(n, false)
result.MergeNulls(arg0)
ds := result.GoDurations()
for i, t := range arg0s {
if result.IsNull(i) {
continue
}
d, err := t.ConvertToDuration()
if err != nil {
return err
}
d, err = d.RoundFrac(int8(b.tp.Decimal))
if err != nil {
return err
}
ds[i] = d.Duration
}
return nil
}

func (b *builtinCastDurationAsDurationSig) vectorized() bool {
Expand Down
20 changes: 20 additions & 0 deletions expression/builtin_cast_vec_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,29 @@ var vecBuiltinCastCases = map[string][]vecExprBenchCase{
{retEvalType: types.ETDuration, childrenTypes: []types.EvalType{types.ETInt}, geners: []dataGenerator{new(randDurInt)}},
{retEvalType: types.ETReal, childrenTypes: []types.EvalType{types.ETReal}},
{retEvalType: types.ETReal, childrenTypes: []types.EvalType{types.ETDecimal}},
{retEvalType: types.ETDuration, childrenTypes: []types.EvalType{types.ETDatetime},
geners: []dataGenerator{&dateTimeGenerWithFsp{
defaultGener: defaultGener{nullRation: 0.2, eType: types.ETDatetime},
fsp: 1,
}},
},
},
}

type dateTimeGenerWithFsp struct {
defaultGener
fsp int8
}

func (g *dateTimeGenerWithFsp) gen() interface{} {
result := g.defaultGener.gen()
if t, ok := result.(types.Time); ok {
t.Fsp = g.fsp
return t
}
return result
}

func (s *testEvaluatorSuite) TestVectorizedBuiltinCastEvalOneVec(c *C) {
testVectorizedEvalOneVec(c, vecBuiltinCastCases)
}
Expand Down
Loading

0 comments on commit 35e308f

Please sign in to comment.