github.com/whtcorpsinc/milevadb-prod@v0.0.0-20211104133533-f57f4be3b597/dbs/memristed/memex/bench_test.go (about) 1 // Copyright 2020 WHTCORPS INC, Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // See the License for the specific language governing permissions and 12 // limitations under the License. 13 14 package memex 15 16 // This file contains benchmarks of our memex evaluation. 17 18 import ( 19 "flag" 20 "fmt" 21 "math/rand" 22 "net" 23 "reflect" 24 "strconv" 25 "strings" 26 "testing" 27 "time" 28 29 . "github.com/whtcorpsinc/check" 30 "github.com/whtcorpsinc/BerolinaSQL/ast" 31 "github.com/whtcorpsinc/BerolinaSQL/auth" 32 "github.com/whtcorpsinc/BerolinaSQL/charset" 33 "github.com/whtcorpsinc/BerolinaSQL/allegrosql" 34 "github.com/whtcorpsinc/BerolinaSQL/terror" 35 "github.com/whtcorpsinc/milevadb/stochastikctx" 36 "github.com/whtcorpsinc/milevadb/stochastikctx/variable" 37 "github.com/whtcorpsinc/milevadb/types" 38 "github.com/whtcorpsinc/milevadb/types/json" 39 "github.com/whtcorpsinc/milevadb/soliton/chunk" 40 "github.com/whtcorpsinc/milevadb/soliton/math" 41 "github.com/whtcorpsinc/milevadb/soliton/mock" 42 ) 43 44 type benchHelper struct { 45 ctx stochastikctx.Context 46 exprs []Expression 47 48 inputTypes []*types.FieldType 49 outputTypes []*types.FieldType 50 inputChunk *chunk.Chunk 51 outputChunk *chunk.Chunk 52 } 53 54 func (h *benchHelper) init() { 55 numEvents := 4 * 1024 56 57 h.ctx = mock.NewContext() 58 h.ctx.GetStochastikVars().StmtCtx.TimeZone = time.Local 59 h.ctx.GetStochastikVars().InitChunkSize = 32 60 h.ctx.GetStochastikVars().MaxChunkSize = numEvents 61 62 h.inputTypes = make([]*types.FieldType, 0, 10) 63 h.inputTypes = append(h.inputTypes, &types.FieldType{ 64 Tp: allegrosql.TypeLonglong, 65 Flen: allegrosql.MaxIntWidth, 66 Decimal: 0, 67 Flag: allegrosql.BinaryFlag, 68 Charset: charset.CharsetBin, 69 DefCauslate: charset.DefCauslationBin, 70 }) 71 h.inputTypes = append(h.inputTypes, &types.FieldType{ 72 Tp: allegrosql.TypeDouble, 73 Flen: allegrosql.MaxRealWidth, 74 Decimal: types.UnspecifiedLength, 75 Flag: allegrosql.BinaryFlag, 76 Charset: charset.CharsetBin, 77 DefCauslate: charset.DefCauslationBin, 78 }) 79 h.inputTypes = append(h.inputTypes, &types.FieldType{ 80 Tp: allegrosql.TypeNewDecimal, 81 Flen: 11, 82 Decimal: 0, 83 Flag: allegrosql.BinaryFlag, 84 Charset: charset.CharsetBin, 85 DefCauslate: charset.DefCauslationBin, 86 }) 87 88 // Use 20 string defCausumns to show the cache performance. 89 for i := 0; i < 20; i++ { 90 h.inputTypes = append(h.inputTypes, &types.FieldType{ 91 Tp: allegrosql.TypeVarString, 92 Flen: 0, 93 Decimal: types.UnspecifiedLength, 94 Charset: charset.CharsetUTF8, 95 DefCauslate: charset.DefCauslationUTF8, 96 }) 97 } 98 99 h.inputChunk = chunk.NewChunkWithCapacity(h.inputTypes, numEvents) 100 for rowIdx := 0; rowIdx < numEvents; rowIdx++ { 101 h.inputChunk.AppendInt64(0, 4) 102 h.inputChunk.AppendFloat64(1, 2.019) 103 h.inputChunk.AppendMyDecimal(2, types.NewDecFromFloatForTest(5.9101)) 104 for i := 0; i < 20; i++ { 105 h.inputChunk.AppendString(3+i, `abcdefughasfjsaljal1321798273528791!&(*#&@&^%&%^&!)sadfashqwer`) 106 } 107 } 108 109 defcaus := make([]*DeferredCauset, 0, len(h.inputTypes)) 110 for i := 0; i < len(h.inputTypes); i++ { 111 defcaus = append(defcaus, &DeferredCauset{ 112 UniqueID: int64(i), 113 RetType: h.inputTypes[i], 114 Index: i, 115 }) 116 } 117 118 h.exprs = make([]Expression, 0, 10) 119 if expr, err := NewFunction(h.ctx, ast.Substr, h.inputTypes[3], []Expression{defcaus[3], defcaus[2]}...); err != nil { 120 panic("create SUBSTR function failed.") 121 } else { 122 h.exprs = append(h.exprs, expr) 123 } 124 125 if expr, err := NewFunction(h.ctx, ast.Plus, h.inputTypes[0], []Expression{defcaus[1], defcaus[2]}...); err != nil { 126 panic("create PLUS function failed.") 127 } else { 128 h.exprs = append(h.exprs, expr) 129 } 130 131 if expr, err := NewFunction(h.ctx, ast.GT, h.inputTypes[2], []Expression{defcaus[11], defcaus[8]}...); err != nil { 132 panic("create GT function failed.") 133 } else { 134 h.exprs = append(h.exprs, expr) 135 } 136 137 if expr, err := NewFunction(h.ctx, ast.GT, h.inputTypes[2], []Expression{defcaus[19], defcaus[10]}...); err != nil { 138 panic("create GT function failed.") 139 } else { 140 h.exprs = append(h.exprs, expr) 141 } 142 143 if expr, err := NewFunction(h.ctx, ast.GT, h.inputTypes[2], []Expression{defcaus[17], defcaus[4]}...); err != nil { 144 panic("create GT function failed.") 145 } else { 146 h.exprs = append(h.exprs, expr) 147 } 148 149 if expr, err := NewFunction(h.ctx, ast.GT, h.inputTypes[2], []Expression{defcaus[18], defcaus[5]}...); err != nil { 150 panic("create GT function failed.") 151 } else { 152 h.exprs = append(h.exprs, expr) 153 } 154 155 if expr, err := NewFunction(h.ctx, ast.LE, h.inputTypes[2], []Expression{defcaus[19], defcaus[4]}...); err != nil { 156 panic("create LE function failed.") 157 } else { 158 h.exprs = append(h.exprs, expr) 159 } 160 161 if expr, err := NewFunction(h.ctx, ast.EQ, h.inputTypes[2], []Expression{defcaus[20], defcaus[3]}...); err != nil { 162 panic("create EQ function failed.") 163 } else { 164 h.exprs = append(h.exprs, expr) 165 } 166 h.exprs = append(h.exprs, defcaus[2]) 167 h.exprs = append(h.exprs, defcaus[2]) 168 169 h.outputTypes = make([]*types.FieldType, 0, len(h.exprs)) 170 for i := 0; i < len(h.exprs); i++ { 171 h.outputTypes = append(h.outputTypes, h.exprs[i].GetType()) 172 } 173 174 h.outputChunk = chunk.NewChunkWithCapacity(h.outputTypes, numEvents) 175 } 176 177 func BenchmarkVectorizedInterDircute(b *testing.B) { 178 h := benchHelper{} 179 h.init() 180 inputIter := chunk.NewIterator4Chunk(h.inputChunk) 181 182 b.ResetTimer() 183 for i := 0; i < b.N; i++ { 184 h.outputChunk.Reset() 185 if err := VectorizedInterDircute(h.ctx, h.exprs, inputIter, h.outputChunk); err != nil { 186 panic("errors happened during \"VectorizedInterDircute\"") 187 } 188 } 189 } 190 191 func BenchmarkScalarFunctionClone(b *testing.B) { 192 defCaus := &DeferredCauset{RetType: types.NewFieldType(allegrosql.TypeLonglong)} 193 con1 := NewOne() 194 con2 := NewZero() 195 add := NewFunctionInternal(mock.NewContext(), ast.Plus, types.NewFieldType(allegrosql.TypeLonglong), defCaus, con1) 196 sub := NewFunctionInternal(mock.NewContext(), ast.Plus, types.NewFieldType(allegrosql.TypeLonglong), add, con2) 197 b.ResetTimer() 198 for i := 0; i < b.N; i++ { 199 sub.Clone() 200 } 201 b.ReportAllocs() 202 } 203 204 func getRandomTime(r *rand.Rand) types.CoreTime { 205 return types.FromDate(r.Intn(2200), r.Intn(10)+1, r.Intn(20)+1, 206 r.Intn(12), r.Intn(60), r.Intn(60), r.Intn(1000000)) 207 208 } 209 210 // dataGenerator is used to generate data for test. 211 type dataGenerator interface { 212 gen() interface{} 213 } 214 215 type defaultRandGen struct { 216 *rand.Rand 217 } 218 219 func newDefaultRandGen() *defaultRandGen { 220 return &defaultRandGen{rand.New(rand.NewSource(int64(rand.Uint64())))} 221 } 222 223 type defaultGener struct { 224 nullRation float64 225 eType types.EvalType 226 randGen *defaultRandGen 227 } 228 229 func newDefaultGener(nullRation float64, eType types.EvalType) *defaultGener { 230 return &defaultGener{ 231 nullRation: nullRation, 232 eType: eType, 233 randGen: newDefaultRandGen(), 234 } 235 } 236 237 func (g *defaultGener) gen() interface{} { 238 if g.randGen.Float64() < g.nullRation { 239 return nil 240 } 241 switch g.eType { 242 case types.ETInt: 243 if g.randGen.Float64() < 0.5 { 244 return -g.randGen.Int63() 245 } 246 return g.randGen.Int63() 247 case types.ETReal: 248 if g.randGen.Float64() < 0.5 { 249 return -g.randGen.Float64() * 1000000 250 } 251 return g.randGen.Float64() * 1000000 252 case types.ETDecimal: 253 d := new(types.MyDecimal) 254 var f float64 255 if g.randGen.Float64() < 0.5 { 256 f = g.randGen.Float64() * 100000 257 } else { 258 f = -g.randGen.Float64() * 100000 259 } 260 if err := d.FromFloat64(f); err != nil { 261 panic(err) 262 } 263 return d 264 case types.ETDatetime, types.ETTimestamp: 265 gt := getRandomTime(g.randGen.Rand) 266 t := types.NewTime(gt, convertETType(g.eType), 0) 267 return t 268 case types.ETDuration: 269 d := types.Duration{ 270 // use rand.Int32() to make it not overflow when AddDuration 271 Duration: time.Duration(g.randGen.Int31()), 272 } 273 return d 274 case types.ETJson: 275 j := new(json.BinaryJSON) 276 if err := j.UnmarshalJSON([]byte(fmt.Sprintf(`{"key":%v}`, g.randGen.Int()))); err != nil { 277 panic(err) 278 } 279 return *j 280 case types.ETString: 281 return randString(g.randGen.Rand) 282 } 283 return nil 284 } 285 286 // charInt64Gener is used to generate int which is equal to char's ascii 287 type charInt64Gener struct{} 288 289 func (g *charInt64Gener) gen() interface{} { 290 rand := time.Now().Nanosecond() 291 rand = rand % 1024 292 return int64(rand) 293 } 294 295 // charsetStringGener is used to generate "ascii" or "gbk" 296 type charsetStringGener struct{} 297 298 func (g *charsetStringGener) gen() interface{} { 299 rand := time.Now().Nanosecond() % 3 300 if rand == 0 { 301 return "ascii" 302 } 303 if rand == 1 { 304 return "utf8" 305 } 306 return "gbk" 307 } 308 309 // selectStringGener select one string randomly from the candidates array 310 type selectStringGener struct { 311 candidates []string 312 randGen *defaultRandGen 313 } 314 315 func newSelectStringGener(candidates []string) *selectStringGener { 316 return &selectStringGener{candidates, newDefaultRandGen()} 317 } 318 319 func (g *selectStringGener) gen() interface{} { 320 if len(g.candidates) == 0 { 321 return nil 322 } 323 return g.candidates[g.randGen.Intn(len(g.candidates))] 324 } 325 326 // selectRealGener select one real number randomly from the candidates array 327 type selectRealGener struct { 328 candidates []float64 329 randGen *defaultRandGen 330 } 331 332 func newSelectRealGener(candidates []float64) *selectRealGener { 333 return &selectRealGener{candidates, newDefaultRandGen()} 334 } 335 336 func (g *selectRealGener) gen() interface{} { 337 if len(g.candidates) == 0 { 338 return nil 339 } 340 return g.candidates[g.randGen.Intn(len(g.candidates))] 341 } 342 343 type constJSONGener struct { 344 jsonStr string 345 } 346 347 func (g *constJSONGener) gen() interface{} { 348 j := new(json.BinaryJSON) 349 if err := j.UnmarshalJSON([]byte(g.jsonStr)); err != nil { 350 panic(err) 351 } 352 return *j 353 } 354 355 type decimalJSONGener struct { 356 nullRation float64 357 randGen *defaultRandGen 358 } 359 360 func newDecimalJSONGener(nullRation float64) *decimalJSONGener { 361 return &decimalJSONGener{nullRation, newDefaultRandGen()} 362 } 363 364 func (g *decimalJSONGener) gen() interface{} { 365 if g.randGen.Float64() < g.nullRation { 366 return nil 367 } 368 369 var f float64 370 if g.randGen.Float64() < 0.5 { 371 f = g.randGen.Float64() * 100000 372 } else { 373 f = -g.randGen.Float64() * 100000 374 } 375 if err := (&types.MyDecimal{}).FromFloat64(f); err != nil { 376 panic(err) 377 } 378 return json.CreateBinary(f) 379 } 380 381 type jsonStringGener struct { 382 randGen *defaultRandGen 383 } 384 385 func newJSONStringGener() *jsonStringGener { 386 return &jsonStringGener{newDefaultRandGen()} 387 } 388 389 func (g *jsonStringGener) gen() interface{} { 390 j := new(json.BinaryJSON) 391 if err := j.UnmarshalJSON([]byte(fmt.Sprintf(`{"key":%v}`, g.randGen.Int()))); err != nil { 392 panic(err) 393 } 394 return j.String() 395 } 396 397 type decimalStringGener struct { 398 randGen *defaultRandGen 399 } 400 401 func newDecimalStringGener() *decimalStringGener { 402 return &decimalStringGener{newDefaultRandGen()} 403 } 404 405 func (g *decimalStringGener) gen() interface{} { 406 temFIDelecimal := new(types.MyDecimal) 407 if err := temFIDelecimal.FromFloat64(g.randGen.Float64()); err != nil { 408 panic(err) 409 } 410 return temFIDelecimal.String() 411 } 412 413 type realStringGener struct { 414 randGen *defaultRandGen 415 } 416 417 func newRealStringGener() *realStringGener { 418 return &realStringGener{newDefaultRandGen()} 419 } 420 421 func (g *realStringGener) gen() interface{} { 422 return fmt.Sprintf("%f", g.randGen.Float64()) 423 } 424 425 type jsonTimeGener struct { 426 randGen *defaultRandGen 427 } 428 429 func newJSONTimeGener() *jsonTimeGener { 430 return &jsonTimeGener{newDefaultRandGen()} 431 } 432 433 func (g *jsonTimeGener) gen() interface{} { 434 tm := types.NewTime(getRandomTime(g.randGen.Rand), allegrosql.TypeDatetime, types.DefaultFsp) 435 return json.CreateBinary(tm.String()) 436 } 437 438 type rangeDurationGener struct { 439 nullRation float64 440 randGen *defaultRandGen 441 } 442 443 func newRangeDurationGener(nullRation float64) *rangeDurationGener { 444 return &rangeDurationGener{nullRation, newDefaultRandGen()} 445 } 446 447 func (g *rangeDurationGener) gen() interface{} { 448 if g.randGen.Float64() < g.nullRation { 449 return nil 450 } 451 tm := (math.Abs(g.randGen.Int63n(12))*3600 + math.Abs(g.randGen.Int63n(60))*60 + math.Abs(g.randGen.Int63n(60))) * 1000 452 tu := (tm + math.Abs(g.randGen.Int63n(1000))) * 1000 453 return types.Duration{ 454 Duration: time.Duration(tu * 1000)} 455 } 456 457 type timeFormatGener struct { 458 nullRation float64 459 randGen *defaultRandGen 460 } 461 462 func newTimeFormatGener(nullRation float64) *timeFormatGener { 463 return &timeFormatGener{nullRation, newDefaultRandGen()} 464 } 465 466 func (g *timeFormatGener) gen() interface{} { 467 if g.randGen.Float64() < g.nullRation { 468 return nil 469 } 470 switch g.randGen.Uint32() % 4 { 471 case 0: 472 return "%H %i %S" 473 case 1: 474 return "%l %i %s" 475 case 2: 476 return "%p %i %s" 477 case 3: 478 return "%I %i %S %f" 479 case 4: 480 return "%T" 481 default: 482 return nil 483 } 484 } 485 486 // rangeRealGener is used to generate float64 items in [begin, end]. 487 type rangeRealGener struct { 488 begin float64 489 end float64 490 491 nullRation float64 492 randGen *defaultRandGen 493 } 494 495 func newRangeRealGener(begin, end, nullRation float64) *rangeRealGener { 496 return &rangeRealGener{begin, end, nullRation, newDefaultRandGen()} 497 } 498 499 func (g *rangeRealGener) gen() interface{} { 500 if g.randGen.Float64() < g.nullRation { 501 return nil 502 } 503 if g.end < g.begin { 504 g.begin = -100 505 g.end = 100 506 } 507 return g.randGen.Float64()*(g.end-g.begin) + g.begin 508 } 509 510 // rangeDecimalGener is used to generate decimal items in [begin, end]. 511 type rangeDecimalGener struct { 512 begin float64 513 end float64 514 515 nullRation float64 516 randGen *defaultRandGen 517 } 518 519 func newRangeDecimalGener(begin, end, nullRation float64) *rangeDecimalGener { 520 return &rangeDecimalGener{begin, end, nullRation, newDefaultRandGen()} 521 } 522 523 func (g *rangeDecimalGener) gen() interface{} { 524 if g.randGen.Float64() < g.nullRation { 525 return nil 526 } 527 if g.end < g.begin { 528 g.begin = -100000 529 g.end = 100000 530 } 531 d := new(types.MyDecimal) 532 f := g.randGen.Float64()*(g.end-g.begin) + g.begin 533 if err := d.FromFloat64(f); err != nil { 534 panic(err) 535 } 536 return d 537 } 538 539 // rangeInt64Gener is used to generate int64 items in [begin, end). 540 type rangeInt64Gener struct { 541 begin int 542 end int 543 randGen *defaultRandGen 544 } 545 546 func newRangeInt64Gener(begin, end int) *rangeInt64Gener { 547 return &rangeInt64Gener{begin, end, newDefaultRandGen()} 548 } 549 550 func (rig *rangeInt64Gener) gen() interface{} { 551 return int64(rig.randGen.Intn(rig.end-rig.begin) + rig.begin) 552 } 553 554 // numStrGener is used to generate number strings. 555 type numStrGener struct { 556 rangeInt64Gener 557 } 558 559 func (g *numStrGener) gen() interface{} { 560 return fmt.Sprintf("%v", g.rangeInt64Gener.gen()) 561 } 562 563 // ipv6StrGener is used to generate ipv6 strings. 564 type ipv6StrGener struct { 565 randGen *defaultRandGen 566 } 567 568 func (g *ipv6StrGener) gen() interface{} { 569 var ip net.IP = make([]byte, net.IPv6len) 570 for i := range ip { 571 ip[i] = uint8(g.randGen.Intn(256)) 572 } 573 return ip.String() 574 } 575 576 // ipv4StrGener is used to generate ipv4 strings. For example 111.111.111.111 577 type ipv4StrGener struct { 578 randGen *defaultRandGen 579 } 580 581 func (g *ipv4StrGener) gen() interface{} { 582 var ip net.IP = make([]byte, net.IPv4len) 583 for i := range ip { 584 ip[i] = uint8(g.randGen.Intn(256)) 585 } 586 return ip.String() 587 } 588 589 // ipv6ByteGener is used to generate ipv6 address in 16 bytes string. 590 type ipv6ByteGener struct { 591 randGen *defaultRandGen 592 } 593 594 func (g *ipv6ByteGener) gen() interface{} { 595 var ip = make([]byte, net.IPv6len) 596 for i := range ip { 597 ip[i] = uint8(g.randGen.Intn(256)) 598 } 599 return string(ip[:net.IPv6len]) 600 } 601 602 // ipv4ByteGener is used to generate ipv4 address in 4 bytes string. 603 type ipv4ByteGener struct { 604 randGen *defaultRandGen 605 } 606 607 func (g *ipv4ByteGener) gen() interface{} { 608 var ip = make([]byte, net.IPv4len) 609 for i := range ip { 610 ip[i] = uint8(g.randGen.Intn(256)) 611 } 612 return string(ip[:net.IPv4len]) 613 } 614 615 // ipv4Compat is used to generate ipv4 compatible ipv6 strings 616 type ipv4CompatByteGener struct { 617 randGen *defaultRandGen 618 } 619 620 func (g *ipv4CompatByteGener) gen() interface{} { 621 var ip = make([]byte, net.IPv6len) 622 for i := range ip { 623 if i < 12 { 624 ip[i] = 0 625 } else { 626 ip[i] = uint8(g.randGen.Intn(256)) 627 } 628 } 629 return string(ip[:net.IPv6len]) 630 } 631 632 // ipv4MappedByteGener is used to generate ipv4-mapped ipv6 bytes. 633 type ipv4MappedByteGener struct { 634 randGen *defaultRandGen 635 } 636 637 func (g *ipv4MappedByteGener) gen() interface{} { 638 var ip = []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, 0, 0, 0, 0} 639 for i := 12; i < 16; i++ { 640 ip[i] = uint8(g.randGen.Intn(256)) // reset the last 4 bytes 641 } 642 return string(ip[:net.IPv6len]) 643 } 644 645 // randLenStrGener is used to generate strings whose lengths are in [lenBegin, lenEnd). 646 type randLenStrGener struct { 647 lenBegin int 648 lenEnd int 649 randGen *defaultRandGen 650 } 651 652 func newRandLenStrGener(lenBegin, lenEnd int) *randLenStrGener { 653 return &randLenStrGener{lenBegin, lenEnd, newDefaultRandGen()} 654 } 655 656 func (g *randLenStrGener) gen() interface{} { 657 n := g.randGen.Intn(g.lenEnd-g.lenBegin) + g.lenBegin 658 buf := make([]byte, n) 659 for i := range buf { 660 x := g.randGen.Intn(62) 661 if x < 10 { 662 buf[i] = byte('0' + x) 663 } else if x-10 < 26 { 664 buf[i] = byte('a' + x - 10) 665 } else { 666 buf[i] = byte('A' + x - 10 - 26) 667 } 668 } 669 return string(buf) 670 } 671 672 type randHexStrGener struct { 673 lenBegin int 674 lenEnd int 675 randGen *defaultRandGen 676 } 677 678 func newRandHexStrGener(lenBegin, lenEnd int) *randHexStrGener { 679 return &randHexStrGener{lenBegin, lenEnd, newDefaultRandGen()} 680 } 681 682 func (g *randHexStrGener) gen() interface{} { 683 n := g.randGen.Intn(g.lenEnd-g.lenBegin) + g.lenBegin 684 buf := make([]byte, n) 685 for i := range buf { 686 x := g.randGen.Intn(16) 687 if x < 10 { 688 buf[i] = byte('0' + x) 689 } else { 690 if x%2 == 0 { 691 buf[i] = byte('a' + x - 10) 692 } else { 693 buf[i] = byte('A' + x - 10) 694 } 695 } 696 } 697 return string(buf) 698 } 699 700 // dateTimeGener is used to generate a dataTime 701 type dateTimeGener struct { 702 Fsp int 703 Year int 704 Month int 705 Day int 706 randGen *defaultRandGen 707 } 708 709 func newDateTimeGener(fsp, year, month, day int) *dateTimeGener { 710 return &dateTimeGener{fsp, year, month, day, newDefaultRandGen()} 711 } 712 713 func (g *dateTimeGener) gen() interface{} { 714 if g.Year == 0 { 715 g.Year = 1970 + g.randGen.Intn(100) 716 } 717 if g.Month == 0 { 718 g.Month = g.randGen.Intn(10) + 1 719 } 720 if g.Day == 0 { 721 g.Day = g.randGen.Intn(20) + 1 722 } 723 var gt types.CoreTime 724 if g.Fsp > 0 && g.Fsp <= 6 { 725 gt = types.FromDate(g.Year, g.Month, g.Day, g.randGen.Intn(12), g.randGen.Intn(60), g.randGen.Intn(60), g.randGen.Intn(1000000)) 726 } else { 727 gt = types.FromDate(g.Year, g.Month, g.Day, g.randGen.Intn(12), g.randGen.Intn(60), g.randGen.Intn(60), 0) 728 } 729 t := types.NewTime(gt, allegrosql.TypeDatetime, types.DefaultFsp) 730 return t 731 } 732 733 // dateTimeStrGener is used to generate strings which are dataTime format 734 type dateTimeStrGener struct { 735 Fsp int 736 Year int 737 Month int 738 Day int 739 randGen *defaultRandGen 740 } 741 742 func (g *dateTimeStrGener) gen() interface{} { 743 if g.Year == 0 { 744 g.Year = 1970 + g.randGen.Intn(100) 745 } 746 if g.Month == 0 { 747 g.Month = g.randGen.Intn(10) + 1 748 } 749 if g.Day == 0 { 750 g.Day = g.randGen.Intn(20) + 1 751 } 752 hour := g.randGen.Intn(12) 753 minute := g.randGen.Intn(60) 754 second := g.randGen.Intn(60) 755 dataTimeStr := fmt.Sprintf("%d-%d-%d %d:%d:%d", 756 g.Year, g.Month, g.Day, hour, minute, second) 757 if g.Fsp > 0 && g.Fsp <= 6 { 758 microFmt := fmt.Sprintf(".%%0%dd", g.Fsp) 759 return dataTimeStr + fmt.Sprintf(microFmt, g.randGen.Int()%(10^g.Fsp)) 760 } 761 762 return dataTimeStr 763 } 764 765 // dateStrGener is used to generate strings which are date format 766 type dateStrGener struct { 767 Year int 768 Month int 769 Day int 770 NullRation float64 771 randGen *defaultRandGen 772 } 773 774 func (g *dateStrGener) gen() interface{} { 775 if g.NullRation > 1e-6 && g.randGen.Float64() < g.NullRation { 776 return nil 777 } 778 779 if g.Year == 0 { 780 g.Year = 1970 + g.randGen.Intn(100) 781 } 782 if g.Month == 0 { 783 g.Month = g.randGen.Intn(10) + 1 784 } 785 if g.Day == 0 { 786 g.Day = g.randGen.Intn(20) + 1 787 } 788 789 return fmt.Sprintf("%d-%d-%d", g.Year, g.Month, g.Day) 790 } 791 792 // timeStrGener is used to generate strings which are time format 793 type timeStrGener struct { 794 nullRation float64 795 randGen *defaultRandGen 796 } 797 798 func (g *timeStrGener) gen() interface{} { 799 if g.nullRation > 1e-6 && g.randGen.Float64() < g.nullRation { 800 return nil 801 } 802 hour := g.randGen.Intn(12) 803 minute := g.randGen.Intn(60) 804 second := g.randGen.Intn(60) 805 806 return fmt.Sprintf("%d:%d:%d", hour, minute, second) 807 } 808 809 type dateTimeIntGener struct { 810 dateTimeGener 811 nullRation float64 812 } 813 814 func (g *dateTimeIntGener) gen() interface{} { 815 if g.randGen.Float64() < g.nullRation { 816 return nil 817 } 818 819 t := g.dateTimeGener.gen().(types.Time) 820 num, err := t.ToNumber().ToInt() 821 if err != nil { 822 panic(err) 823 } 824 return num 825 } 826 827 // constStrGener always returns the given string 828 type constStrGener struct { 829 s string 830 } 831 832 func (g *constStrGener) gen() interface{} { 833 return g.s 834 } 835 836 type randDurInt struct { 837 randGen *defaultRandGen 838 } 839 840 func newRandDurInt() *randDurInt { 841 return &randDurInt{newDefaultRandGen()} 842 } 843 844 func (g *randDurInt) gen() interface{} { 845 return int64(g.randGen.Intn(types.TimeMaxHour)*10000 + g.randGen.Intn(60)*100 + g.randGen.Intn(60)) 846 } 847 848 type randDurReal struct { 849 randGen *defaultRandGen 850 } 851 852 func newRandDurReal() *randDurReal { 853 return &randDurReal{newDefaultRandGen()} 854 } 855 856 func (g *randDurReal) gen() interface{} { 857 return float64(g.randGen.Intn(types.TimeMaxHour)*10000 + g.randGen.Intn(60)*100 + g.randGen.Intn(60)) 858 } 859 860 type randDurDecimal struct { 861 randGen *defaultRandGen 862 } 863 864 func newRandDurDecimal() *randDurDecimal { 865 return &randDurDecimal{newDefaultRandGen()} 866 } 867 868 func (g *randDurDecimal) gen() interface{} { 869 d := new(types.MyDecimal) 870 return d.FromFloat64(float64(g.randGen.Intn(types.TimeMaxHour)*10000 + g.randGen.Intn(60)*100 + g.randGen.Intn(60))) 871 } 872 873 type randDurString struct{} 874 875 func (g *randDurString) gen() interface{} { 876 return strconv.Itoa(rand.Intn(types.TimeMaxHour)*10000 + rand.Intn(60)*100 + rand.Intn(60)) 877 } 878 879 // locationGener is used to generate location for the built-in function GetFormat. 880 type locationGener struct { 881 nullRation float64 882 randGen *defaultRandGen 883 } 884 885 func newLocationGener(nullRation float64) *locationGener { 886 return &locationGener{nullRation, newDefaultRandGen()} 887 } 888 889 func (g *locationGener) gen() interface{} { 890 if g.randGen.Float64() < g.nullRation { 891 return nil 892 } 893 switch g.randGen.Uint32() % 5 { 894 case 0: 895 return usaLocation 896 case 1: 897 return jisLocation 898 case 2: 899 return isoLocation 900 case 3: 901 return eurLocation 902 case 4: 903 return internalLocation 904 default: 905 return nil 906 } 907 } 908 909 // formatGener is used to generate a format for the built-in function GetFormat. 910 type formatGener struct { 911 nullRation float64 912 randGen *defaultRandGen 913 } 914 915 func newFormatGener(nullRation float64) *formatGener { 916 return &formatGener{nullRation, newDefaultRandGen()} 917 } 918 919 func (g *formatGener) gen() interface{} { 920 if g.randGen.Float64() < g.nullRation { 921 return nil 922 } 923 switch g.randGen.Uint32() % 4 { 924 case 0: 925 return dateFormat 926 case 1: 927 return datetimeFormat 928 case 2: 929 return timestampFormat 930 case 3: 931 return timeFormat 932 default: 933 return nil 934 } 935 } 936 937 type nullWrappedGener struct { 938 nullRation float64 939 inner dataGenerator 940 randGen *defaultRandGen 941 } 942 943 func newNullWrappedGener(nullRation float64, inner dataGenerator) *nullWrappedGener { 944 return &nullWrappedGener{nullRation, inner, newDefaultRandGen()} 945 } 946 947 func (g *nullWrappedGener) gen() interface{} { 948 if g.randGen.Float64() < g.nullRation { 949 return nil 950 } 951 return g.inner.gen() 952 } 953 954 type vecExprBenchCase struct { 955 // retEvalType is the EvalType of the memex result. 956 // This field is required. 957 retEvalType types.EvalType 958 // childrenTypes is the EvalTypes of the memex children(arguments). 959 // This field is required. 960 childrenTypes []types.EvalType 961 // childrenFieldTypes is the field types of the memex children(arguments). 962 // If childrenFieldTypes is not set, it will be converted from childrenTypes. 963 // This field is optional. 964 childrenFieldTypes []*types.FieldType 965 // geners are used to generate data for children and geners[i] generates data for children[i]. 966 // If geners[i] is nil, the default dataGenerator will be used for its corresponding child. 967 // The geners slice can be shorter than the children slice, if it has 3 children, then 968 // geners[gen1, gen2] will be regarded as geners[gen1, gen2, nil]. 969 // This field is optional. 970 geners []dataGenerator 971 // aesModeAttr information, needed by encryption functions 972 aesModes string 973 // constants are used to generate constant data for children[i]. 974 constants []*Constant 975 // chunkSize is used to specify the chunk size of children, the maximum is 1024. 976 // This field is optional, 1024 by default. 977 chunkSize int 978 } 979 980 type vecExprBenchCases map[string][]vecExprBenchCase 981 982 func fillDeferredCauset(eType types.EvalType, chk *chunk.Chunk, defCausIdx int, testCase vecExprBenchCase) { 983 var gen dataGenerator 984 if len(testCase.geners) > defCausIdx && testCase.geners[defCausIdx] != nil { 985 gen = testCase.geners[defCausIdx] 986 } 987 fillDeferredCausetWithGener(eType, chk, defCausIdx, gen) 988 } 989 990 func fillDeferredCausetWithGener(eType types.EvalType, chk *chunk.Chunk, defCausIdx int, gen dataGenerator) { 991 batchSize := chk.Capacity() 992 if gen == nil { 993 gen = newDefaultGener(0.2, eType) 994 } 995 996 defCaus := chk.DeferredCauset(defCausIdx) 997 defCaus.Reset(eType) 998 for i := 0; i < batchSize; i++ { 999 v := gen.gen() 1000 if v == nil { 1001 defCaus.AppendNull() 1002 continue 1003 } 1004 switch eType { 1005 case types.ETInt: 1006 defCaus.AppendInt64(v.(int64)) 1007 case types.ETReal: 1008 defCaus.AppendFloat64(v.(float64)) 1009 case types.ETDecimal: 1010 defCaus.AppendMyDecimal(v.(*types.MyDecimal)) 1011 case types.ETDatetime, types.ETTimestamp: 1012 defCaus.AppendTime(v.(types.Time)) 1013 case types.ETDuration: 1014 defCaus.AppendDuration(v.(types.Duration)) 1015 case types.ETJson: 1016 defCaus.AppendJSON(v.(json.BinaryJSON)) 1017 case types.ETString: 1018 defCaus.AppendString(v.(string)) 1019 } 1020 } 1021 } 1022 1023 func randString(r *rand.Rand) string { 1024 n := 10 + r.Intn(10) 1025 buf := make([]byte, n) 1026 for i := range buf { 1027 x := r.Intn(62) 1028 if x < 10 { 1029 buf[i] = byte('0' + x) 1030 } else if x-10 < 26 { 1031 buf[i] = byte('a' + x - 10) 1032 } else { 1033 buf[i] = byte('A' + x - 10 - 26) 1034 } 1035 } 1036 return string(buf) 1037 } 1038 1039 func eType2FieldType(eType types.EvalType) *types.FieldType { 1040 switch eType { 1041 case types.ETInt: 1042 return types.NewFieldType(allegrosql.TypeLonglong) 1043 case types.ETReal: 1044 return types.NewFieldType(allegrosql.TypeDouble) 1045 case types.ETDecimal: 1046 return types.NewFieldType(allegrosql.TypeNewDecimal) 1047 case types.ETDatetime, types.ETTimestamp: 1048 return types.NewFieldType(allegrosql.TypeDatetime) 1049 case types.ETDuration: 1050 return types.NewFieldType(allegrosql.TypeDuration) 1051 case types.ETJson: 1052 return types.NewFieldType(allegrosql.TypeJSON) 1053 case types.ETString: 1054 return types.NewFieldType(allegrosql.TypeVarString) 1055 default: 1056 panic(fmt.Sprintf("EvalType=%v is not supported.", eType)) 1057 } 1058 } 1059 1060 func genVecExprBenchCase(ctx stochastikctx.Context, funcName string, testCase vecExprBenchCase) (expr Expression, fts []*types.FieldType, input *chunk.Chunk, output *chunk.Chunk) { 1061 fts = make([]*types.FieldType, len(testCase.childrenTypes)) 1062 for i := range fts { 1063 if i < len(testCase.childrenFieldTypes) && testCase.childrenFieldTypes[i] != nil { 1064 fts[i] = testCase.childrenFieldTypes[i] 1065 } else { 1066 fts[i] = eType2FieldType(testCase.childrenTypes[i]) 1067 } 1068 } 1069 if testCase.chunkSize <= 0 || testCase.chunkSize > 1024 { 1070 testCase.chunkSize = 1024 1071 } 1072 defcaus := make([]Expression, len(testCase.childrenTypes)) 1073 input = chunk.New(fts, testCase.chunkSize, testCase.chunkSize) 1074 input.NumEvents() 1075 for i, eType := range testCase.childrenTypes { 1076 fillDeferredCauset(eType, input, i, testCase) 1077 if i < len(testCase.constants) && testCase.constants[i] != nil { 1078 defcaus[i] = testCase.constants[i] 1079 } else { 1080 defcaus[i] = &DeferredCauset{Index: i, RetType: fts[i]} 1081 } 1082 } 1083 1084 expr, err := NewFunction(ctx, funcName, eType2FieldType(testCase.retEvalType), defcaus...) 1085 if err != nil { 1086 panic(err) 1087 } 1088 1089 output = chunk.New([]*types.FieldType{eType2FieldType(expr.GetType().EvalType())}, testCase.chunkSize, testCase.chunkSize) 1090 return expr, fts, input, output 1091 } 1092 1093 // testVectorizedEvalOneVec is used to verify that the vectorized 1094 // memex is evaluated correctly during projection 1095 func testVectorizedEvalOneVec(c *C, vecExprCases vecExprBenchCases) { 1096 ctx := mock.NewContext() 1097 for funcName, testCases := range vecExprCases { 1098 for _, testCase := range testCases { 1099 expr, fts, input, output := genVecExprBenchCase(ctx, funcName, testCase) 1100 commentf := func(event int) CommentInterface { 1101 return Commentf("func: %v, case %+v, event: %v, rowData: %v", funcName, testCase, event, input.GetEvent(event).GetCausetEvent(fts)) 1102 } 1103 output2 := output.CopyConstruct() 1104 c.Assert(evalOneVec(ctx, expr, input, output, 0), IsNil, Commentf("func: %v, case: %+v", funcName, testCase)) 1105 it := chunk.NewIterator4Chunk(input) 1106 c.Assert(evalOneDeferredCauset(ctx, expr, it, output2, 0), IsNil, Commentf("func: %v, case: %+v", funcName, testCase)) 1107 1108 c1, c2 := output.DeferredCauset(0), output2.DeferredCauset(0) 1109 switch expr.GetType().EvalType() { 1110 case types.ETInt: 1111 for i := 0; i < input.NumEvents(); i++ { 1112 c.Assert(c1.IsNull(i), Equals, c2.IsNull(i), commentf(i)) 1113 if !c1.IsNull(i) { 1114 c.Assert(c1.GetInt64(i), Equals, c2.GetInt64(i), commentf(i)) 1115 } 1116 } 1117 case types.ETReal: 1118 for i := 0; i < input.NumEvents(); i++ { 1119 c.Assert(c1.IsNull(i), Equals, c2.IsNull(i), commentf(i)) 1120 if !c1.IsNull(i) { 1121 c.Assert(c1.GetFloat64(i), Equals, c2.GetFloat64(i), commentf(i)) 1122 } 1123 } 1124 case types.ETDecimal: 1125 for i := 0; i < input.NumEvents(); i++ { 1126 c.Assert(c1.IsNull(i), Equals, c2.IsNull(i), commentf(i)) 1127 if !c1.IsNull(i) { 1128 c.Assert(c1.GetDecimal(i), DeepEquals, c2.GetDecimal(i), commentf(i)) 1129 } 1130 } 1131 case types.ETDatetime, types.ETTimestamp: 1132 for i := 0; i < input.NumEvents(); i++ { 1133 c.Assert(c1.IsNull(i), Equals, c2.IsNull(i), commentf(i)) 1134 if !c1.IsNull(i) { 1135 c.Assert(c1.GetTime(i), DeepEquals, c2.GetTime(i), commentf(i)) 1136 } 1137 } 1138 case types.ETDuration: 1139 for i := 0; i < input.NumEvents(); i++ { 1140 c.Assert(c1.IsNull(i), Equals, c2.IsNull(i), commentf(i)) 1141 if !c1.IsNull(i) { 1142 c.Assert(c1.GetDuration(i, 0), Equals, c2.GetDuration(i, 0), commentf(i)) 1143 } 1144 } 1145 case types.ETJson: 1146 for i := 0; i < input.NumEvents(); i++ { 1147 c.Assert(c1.IsNull(i), Equals, c2.IsNull(i), commentf(i)) 1148 if !c1.IsNull(i) { 1149 c.Assert(c1.GetJSON(i), DeepEquals, c2.GetJSON(i), commentf(i)) 1150 } 1151 } 1152 case types.ETString: 1153 for i := 0; i < input.NumEvents(); i++ { 1154 c.Assert(c1.IsNull(i), Equals, c2.IsNull(i), commentf(i)) 1155 if !c1.IsNull(i) { 1156 c.Assert(c1.GetString(i), Equals, c2.GetString(i), commentf(i)) 1157 } 1158 } 1159 } 1160 } 1161 } 1162 } 1163 1164 // benchmarkVectorizedEvalOneVec is used to get the effect of 1165 // using the vectorized memex evaluations during projection 1166 func benchmarkVectorizedEvalOneVec(b *testing.B, vecExprCases vecExprBenchCases) { 1167 ctx := mock.NewContext() 1168 for funcName, testCases := range vecExprCases { 1169 for _, testCase := range testCases { 1170 expr, _, input, output := genVecExprBenchCase(ctx, funcName, testCase) 1171 exprName := expr.String() 1172 if sf, ok := expr.(*ScalarFunction); ok { 1173 exprName = fmt.Sprintf("%v", reflect.TypeOf(sf.Function)) 1174 tmp := strings.Split(exprName, ".") 1175 exprName = tmp[len(tmp)-1] 1176 } 1177 1178 b.Run(exprName+"-EvalOneVec", func(b *testing.B) { 1179 b.ResetTimer() 1180 for i := 0; i < b.N; i++ { 1181 if err := evalOneVec(ctx, expr, input, output, 0); err != nil { 1182 b.Fatal(err) 1183 } 1184 } 1185 }) 1186 b.Run(exprName+"-EvalOneDefCaus", func(b *testing.B) { 1187 b.ResetTimer() 1188 for i := 0; i < b.N; i++ { 1189 it := chunk.NewIterator4Chunk(input) 1190 if err := evalOneDeferredCauset(ctx, expr, it, output, 0); err != nil { 1191 b.Fatal(err) 1192 } 1193 } 1194 }) 1195 } 1196 } 1197 } 1198 1199 func genVecBuiltinFuncBenchCase(ctx stochastikctx.Context, funcName string, testCase vecExprBenchCase) (baseFunc builtinFunc, fts []*types.FieldType, input *chunk.Chunk, result *chunk.DeferredCauset) { 1200 childrenNumber := len(testCase.childrenTypes) 1201 fts = make([]*types.FieldType, childrenNumber) 1202 for i := range fts { 1203 if i < len(testCase.childrenFieldTypes) && testCase.childrenFieldTypes[i] != nil { 1204 fts[i] = testCase.childrenFieldTypes[i] 1205 } else { 1206 fts[i] = eType2FieldType(testCase.childrenTypes[i]) 1207 } 1208 } 1209 defcaus := make([]Expression, childrenNumber) 1210 if testCase.chunkSize <= 0 || testCase.chunkSize > 1024 { 1211 testCase.chunkSize = 1024 1212 } 1213 input = chunk.New(fts, testCase.chunkSize, testCase.chunkSize) 1214 for i, eType := range testCase.childrenTypes { 1215 fillDeferredCauset(eType, input, i, testCase) 1216 if i < len(testCase.constants) && testCase.constants[i] != nil { 1217 defcaus[i] = testCase.constants[i] 1218 } else { 1219 defcaus[i] = &DeferredCauset{Index: i, RetType: fts[i]} 1220 } 1221 } 1222 if len(defcaus) == 0 { 1223 input.SetNumVirtualEvents(testCase.chunkSize) 1224 } 1225 1226 var err error 1227 if funcName == ast.Cast { 1228 var fc functionClass 1229 tp := eType2FieldType(testCase.retEvalType) 1230 switch testCase.retEvalType { 1231 case types.ETInt: 1232 fc = &castAsIntFunctionClass{baseFunctionClass{ast.Cast, 1, 1}, tp} 1233 case types.ETDecimal: 1234 fc = &castAsDecimalFunctionClass{baseFunctionClass{ast.Cast, 1, 1}, tp} 1235 case types.ETReal: 1236 fc = &castAsRealFunctionClass{baseFunctionClass{ast.Cast, 1, 1}, tp} 1237 case types.ETDatetime, types.ETTimestamp: 1238 fc = &castAsTimeFunctionClass{baseFunctionClass{ast.Cast, 1, 1}, tp} 1239 case types.ETDuration: 1240 fc = &castAsDurationFunctionClass{baseFunctionClass{ast.Cast, 1, 1}, tp} 1241 case types.ETJson: 1242 fc = &castAsJSONFunctionClass{baseFunctionClass{ast.Cast, 1, 1}, tp} 1243 case types.ETString: 1244 fc = &castAsStringFunctionClass{baseFunctionClass{ast.Cast, 1, 1}, tp} 1245 } 1246 baseFunc, err = fc.getFunction(ctx, defcaus) 1247 } else { 1248 baseFunc, err = funcs[funcName].getFunction(ctx, defcaus) 1249 } 1250 if err != nil { 1251 panic(err) 1252 } 1253 result = chunk.NewDeferredCauset(eType2FieldType(testCase.retEvalType), testCase.chunkSize) 1254 // Mess up the output to make sure vecEvalXXX to call ResizeXXX/ReserveXXX itself. 1255 result.AppendNull() 1256 return baseFunc, fts, input, result 1257 } 1258 1259 // a replog way to calculate length of a chunk.DeferredCauset. 1260 func getDeferredCausetLen(defCaus *chunk.DeferredCauset, eType types.EvalType) int { 1261 chk := chunk.New([]*types.FieldType{eType2FieldType(eType)}, 1024, 1024) 1262 chk.SetDefCaus(0, defCaus) 1263 return chk.NumEvents() 1264 } 1265 1266 // removeTestOptions removes all not needed options like '-test.timeout=' from argument list 1267 func removeTestOptions(args []string) []string { 1268 argList := args[:0] 1269 1270 // args contains '-test.timeout=' option for example 1271 // excluding it to be able to run all tests 1272 for _, arg := range args { 1273 if strings.HasPrefix(arg, "builtin") || IsFunctionSupported(arg) { 1274 argList = append(argList, arg) 1275 } 1276 } 1277 return argList 1278 } 1279 1280 // testVectorizedBuiltinFunc is used to verify that the vectorized 1281 // memex is evaluated correctly 1282 func testVectorizedBuiltinFunc(c *C, vecExprCases vecExprBenchCases) { 1283 testFunc := make(map[string]bool) 1284 argList := removeTestOptions(flag.Args()) 1285 testAll := len(argList) == 0 1286 for _, arg := range argList { 1287 testFunc[arg] = true 1288 } 1289 for funcName, testCases := range vecExprCases { 1290 for _, testCase := range testCases { 1291 ctx := mock.NewContext() 1292 err := ctx.GetStochastikVars().SetSystemVar(variable.BlockEncryptionMode, testCase.aesModes) 1293 c.Assert(err, IsNil) 1294 if funcName == ast.CurrentUser || funcName == ast.User { 1295 ctx.GetStochastikVars().User = &auth.UserIdentity{ 1296 Username: "milevadb", 1297 Hostname: "localhost", 1298 CurrentUser: true, 1299 AuthHostname: "localhost", 1300 AuthUsername: "milevadb", 1301 } 1302 } 1303 if funcName == ast.GetParam { 1304 testTime := time.Now() 1305 ctx.GetStochastikVars().PreparedParams = []types.Causet{ 1306 types.NewIntCauset(1), 1307 types.NewDecimalCauset(types.NewDecFromStringForTest("20170118123950.123")), 1308 types.NewTimeCauset(types.NewTime(types.FromGoTime(testTime), allegrosql.TypeTimestamp, 6)), 1309 types.NewDurationCauset(types.ZeroDuration), 1310 types.NewStringCauset("{}"), 1311 types.NewBinaryLiteralCauset([]byte{1}), 1312 types.NewBytesCauset([]byte{'b'}), 1313 types.NewFloat32Causet(1.1), 1314 types.NewFloat64Causet(2.1), 1315 types.NewUintCauset(100), 1316 types.NewMysqlBitCauset([]byte{1}), 1317 types.NewMysqlEnumCauset(types.Enum{Name: "n", Value: 2}), 1318 } 1319 } 1320 baseFunc, fts, input, output := genVecBuiltinFuncBenchCase(ctx, funcName, testCase) 1321 baseFuncName := fmt.Sprintf("%v", reflect.TypeOf(baseFunc)) 1322 tmp := strings.Split(baseFuncName, ".") 1323 baseFuncName = tmp[len(tmp)-1] 1324 1325 if !testAll && (testFunc[baseFuncName] != true && testFunc[funcName] != true) { 1326 continue 1327 } 1328 // do not forget to implement the vectorized method. 1329 c.Assert(baseFunc.vectorized(), IsTrue, Commentf("func: %v, case: %+v", baseFuncName, testCase)) 1330 commentf := func(event int) CommentInterface { 1331 return Commentf("func: %v, case %+v, event: %v, rowData: %v", baseFuncName, testCase, event, input.GetEvent(event).GetCausetEvent(fts)) 1332 } 1333 it := chunk.NewIterator4Chunk(input) 1334 i := 0 1335 var vecWarnCnt uint16 1336 switch testCase.retEvalType { 1337 case types.ETInt: 1338 err := baseFunc.vecEvalInt(input, output) 1339 c.Assert(err, IsNil, Commentf("func: %v, case: %+v", baseFuncName, testCase)) 1340 // do not forget to call ResizeXXX/ReserveXXX 1341 c.Assert(getDeferredCausetLen(output, testCase.retEvalType), Equals, input.NumEvents()) 1342 vecWarnCnt = ctx.GetStochastikVars().StmtCtx.WarningCount() 1343 i64s := output.Int64s() 1344 for event := it.Begin(); event != it.End(); event = it.Next() { 1345 val, isNull, err := baseFunc.evalInt(event) 1346 c.Assert(err, IsNil, commentf(i)) 1347 c.Assert(isNull, Equals, output.IsNull(i), commentf(i)) 1348 if !isNull { 1349 c.Assert(val, Equals, i64s[i], commentf(i)) 1350 } 1351 i++ 1352 } 1353 case types.ETReal: 1354 err := baseFunc.vecEvalReal(input, output) 1355 c.Assert(err, IsNil, Commentf("func: %v, case: %+v", baseFuncName, testCase)) 1356 // do not forget to call ResizeXXX/ReserveXXX 1357 c.Assert(getDeferredCausetLen(output, testCase.retEvalType), Equals, input.NumEvents()) 1358 vecWarnCnt = ctx.GetStochastikVars().StmtCtx.WarningCount() 1359 f64s := output.Float64s() 1360 for event := it.Begin(); event != it.End(); event = it.Next() { 1361 val, isNull, err := baseFunc.evalReal(event) 1362 c.Assert(err, IsNil, commentf(i)) 1363 c.Assert(isNull, Equals, output.IsNull(i), commentf(i)) 1364 if !isNull { 1365 c.Assert(val, Equals, f64s[i], commentf(i)) 1366 } 1367 i++ 1368 } 1369 case types.ETDecimal: 1370 err := baseFunc.vecEvalDecimal(input, output) 1371 c.Assert(err, IsNil, Commentf("func: %v, case: %+v", baseFuncName, testCase)) 1372 // do not forget to call ResizeXXX/ReserveXXX 1373 c.Assert(getDeferredCausetLen(output, testCase.retEvalType), Equals, input.NumEvents()) 1374 vecWarnCnt = ctx.GetStochastikVars().StmtCtx.WarningCount() 1375 d64s := output.Decimals() 1376 for event := it.Begin(); event != it.End(); event = it.Next() { 1377 val, isNull, err := baseFunc.evalDecimal(event) 1378 c.Assert(err, IsNil, commentf(i)) 1379 c.Assert(isNull, Equals, output.IsNull(i), commentf(i)) 1380 if !isNull { 1381 c.Assert(*val, Equals, d64s[i], commentf(i)) 1382 } 1383 i++ 1384 } 1385 case types.ETDatetime, types.ETTimestamp: 1386 err := baseFunc.vecEvalTime(input, output) 1387 c.Assert(err, IsNil, Commentf("func: %v, case: %+v", baseFuncName, testCase)) 1388 // do not forget to call ResizeXXX/ReserveXXX 1389 c.Assert(getDeferredCausetLen(output, testCase.retEvalType), Equals, input.NumEvents()) 1390 vecWarnCnt = ctx.GetStochastikVars().StmtCtx.WarningCount() 1391 t64s := output.Times() 1392 for event := it.Begin(); event != it.End(); event = it.Next() { 1393 val, isNull, err := baseFunc.evalTime(event) 1394 c.Assert(err, IsNil, commentf(i)) 1395 c.Assert(isNull, Equals, output.IsNull(i), commentf(i)) 1396 if !isNull { 1397 c.Assert(val, Equals, t64s[i], commentf(i)) 1398 } 1399 i++ 1400 } 1401 case types.ETDuration: 1402 err := baseFunc.vecEvalDuration(input, output) 1403 c.Assert(err, IsNil, Commentf("func: %v, case: %+v", baseFuncName, testCase)) 1404 // do not forget to call ResizeXXX/ReserveXXX 1405 c.Assert(getDeferredCausetLen(output, testCase.retEvalType), Equals, input.NumEvents()) 1406 vecWarnCnt = ctx.GetStochastikVars().StmtCtx.WarningCount() 1407 d64s := output.GoDurations() 1408 for event := it.Begin(); event != it.End(); event = it.Next() { 1409 val, isNull, err := baseFunc.evalDuration(event) 1410 c.Assert(err, IsNil, commentf(i)) 1411 c.Assert(isNull, Equals, output.IsNull(i), commentf(i)) 1412 if !isNull { 1413 c.Assert(val.Duration, Equals, d64s[i], commentf(i)) 1414 } 1415 i++ 1416 } 1417 case types.ETJson: 1418 err := baseFunc.vecEvalJSON(input, output) 1419 c.Assert(err, IsNil, Commentf("func: %v, case: %+v", baseFuncName, testCase)) 1420 // do not forget to call ResizeXXX/ReserveXXX 1421 c.Assert(getDeferredCausetLen(output, testCase.retEvalType), Equals, input.NumEvents()) 1422 vecWarnCnt = ctx.GetStochastikVars().StmtCtx.WarningCount() 1423 for event := it.Begin(); event != it.End(); event = it.Next() { 1424 val, isNull, err := baseFunc.evalJSON(event) 1425 c.Assert(err, IsNil, commentf(i)) 1426 c.Assert(isNull, Equals, output.IsNull(i), commentf(i)) 1427 if !isNull { 1428 cmp := json.CompareBinary(val, output.GetJSON(i)) 1429 c.Assert(cmp, Equals, 0, commentf(i)) 1430 } 1431 i++ 1432 } 1433 case types.ETString: 1434 err := baseFunc.vecEvalString(input, output) 1435 c.Assert(err, IsNil, Commentf("func: %v, case: %+v", baseFuncName, testCase)) 1436 // do not forget to call ResizeXXX/ReserveXXX 1437 c.Assert(getDeferredCausetLen(output, testCase.retEvalType), Equals, input.NumEvents()) 1438 vecWarnCnt = ctx.GetStochastikVars().StmtCtx.WarningCount() 1439 for event := it.Begin(); event != it.End(); event = it.Next() { 1440 val, isNull, err := baseFunc.evalString(event) 1441 c.Assert(err, IsNil, commentf(i)) 1442 c.Assert(isNull, Equals, output.IsNull(i), commentf(i)) 1443 if !isNull { 1444 c.Assert(val, Equals, output.GetString(i), commentf(i)) 1445 } 1446 i++ 1447 } 1448 default: 1449 c.Fatal(fmt.Sprintf("evalType=%v is not supported", testCase.retEvalType)) 1450 } 1451 1452 // check warnings 1453 totalWarns := ctx.GetStochastikVars().StmtCtx.WarningCount() 1454 c.Assert(2*vecWarnCnt, Equals, totalWarns) 1455 warns := ctx.GetStochastikVars().StmtCtx.GetWarnings() 1456 for i := 0; i < int(vecWarnCnt); i++ { 1457 c.Assert(terror.ErrorEqual(warns[i].Err, warns[i+int(vecWarnCnt)].Err), IsTrue) 1458 } 1459 } 1460 } 1461 } 1462 1463 // testVectorizedBuiltinFuncForRand is used to verify that the vectorized 1464 // memex is evaluated correctly 1465 func testVectorizedBuiltinFuncForRand(c *C, vecExprCases vecExprBenchCases) { 1466 for funcName, testCases := range vecExprCases { 1467 c.Assert(strings.EqualFold("rand", funcName), Equals, true) 1468 1469 for _, testCase := range testCases { 1470 c.Assert(len(testCase.childrenTypes), Equals, 0) 1471 1472 ctx := mock.NewContext() 1473 baseFunc, _, input, output := genVecBuiltinFuncBenchCase(ctx, funcName, testCase) 1474 baseFuncName := fmt.Sprintf("%v", reflect.TypeOf(baseFunc)) 1475 tmp := strings.Split(baseFuncName, ".") 1476 baseFuncName = tmp[len(tmp)-1] 1477 // do not forget to implement the vectorized method. 1478 c.Assert(baseFunc.vectorized(), IsTrue, Commentf("func: %v", baseFuncName)) 1479 switch testCase.retEvalType { 1480 case types.ETReal: 1481 err := baseFunc.vecEvalReal(input, output) 1482 c.Assert(err, IsNil) 1483 // do not forget to call ResizeXXX/ReserveXXX 1484 c.Assert(getDeferredCausetLen(output, testCase.retEvalType), Equals, input.NumEvents()) 1485 // check result 1486 res := output.Float64s() 1487 for _, v := range res { 1488 c.Assert((0 <= v) && (v < 1), Equals, true) 1489 } 1490 default: 1491 c.Fatal(fmt.Sprintf("evalType=%v is not supported", testCase.retEvalType)) 1492 } 1493 } 1494 } 1495 } 1496 1497 // benchmarkVectorizedBuiltinFunc is used to get the effect of 1498 // using the vectorized memex evaluations 1499 func benchmarkVectorizedBuiltinFunc(b *testing.B, vecExprCases vecExprBenchCases) { 1500 ctx := mock.NewContext() 1501 testFunc := make(map[string]bool) 1502 argList := removeTestOptions(flag.Args()) 1503 testAll := len(argList) == 0 1504 for _, arg := range argList { 1505 testFunc[arg] = true 1506 } 1507 for funcName, testCases := range vecExprCases { 1508 for _, testCase := range testCases { 1509 err := ctx.GetStochastikVars().SetSystemVar(variable.BlockEncryptionMode, testCase.aesModes) 1510 if err != nil { 1511 panic(err) 1512 } 1513 if funcName == ast.CurrentUser || funcName == ast.User { 1514 ctx.GetStochastikVars().User = &auth.UserIdentity{ 1515 Username: "milevadb", 1516 Hostname: "localhost", 1517 CurrentUser: true, 1518 AuthHostname: "localhost", 1519 AuthUsername: "milevadb", 1520 } 1521 } 1522 if funcName == ast.GetParam { 1523 testTime := time.Now() 1524 ctx.GetStochastikVars().PreparedParams = []types.Causet{ 1525 types.NewIntCauset(1), 1526 types.NewDecimalCauset(types.NewDecFromStringForTest("20170118123950.123")), 1527 types.NewTimeCauset(types.NewTime(types.FromGoTime(testTime), allegrosql.TypeTimestamp, 6)), 1528 types.NewDurationCauset(types.ZeroDuration), 1529 types.NewStringCauset("{}"), 1530 types.NewBinaryLiteralCauset([]byte{1}), 1531 types.NewBytesCauset([]byte{'b'}), 1532 types.NewFloat32Causet(1.1), 1533 types.NewFloat64Causet(2.1), 1534 types.NewUintCauset(100), 1535 types.NewMysqlBitCauset([]byte{1}), 1536 types.NewMysqlEnumCauset(types.Enum{Name: "n", Value: 2}), 1537 } 1538 } 1539 baseFunc, _, input, output := genVecBuiltinFuncBenchCase(ctx, funcName, testCase) 1540 baseFuncName := fmt.Sprintf("%v", reflect.TypeOf(baseFunc)) 1541 tmp := strings.Split(baseFuncName, ".") 1542 baseFuncName = tmp[len(tmp)-1] 1543 1544 if !testAll && testFunc[baseFuncName] != true && testFunc[funcName] != true { 1545 continue 1546 } 1547 1548 b.Run(baseFuncName+"-VecBuiltinFunc", func(b *testing.B) { 1549 b.ResetTimer() 1550 switch testCase.retEvalType { 1551 case types.ETInt: 1552 for i := 0; i < b.N; i++ { 1553 if err := baseFunc.vecEvalInt(input, output); err != nil { 1554 b.Fatal(err) 1555 } 1556 } 1557 case types.ETReal: 1558 for i := 0; i < b.N; i++ { 1559 if err := baseFunc.vecEvalReal(input, output); err != nil { 1560 b.Fatal(err) 1561 } 1562 } 1563 case types.ETDecimal: 1564 for i := 0; i < b.N; i++ { 1565 if err := baseFunc.vecEvalDecimal(input, output); err != nil { 1566 b.Fatal(err) 1567 } 1568 } 1569 case types.ETDatetime, types.ETTimestamp: 1570 for i := 0; i < b.N; i++ { 1571 if err := baseFunc.vecEvalTime(input, output); err != nil { 1572 b.Fatal(err) 1573 } 1574 } 1575 case types.ETDuration: 1576 for i := 0; i < b.N; i++ { 1577 if err := baseFunc.vecEvalDuration(input, output); err != nil { 1578 b.Fatal(err) 1579 } 1580 } 1581 case types.ETJson: 1582 for i := 0; i < b.N; i++ { 1583 if err := baseFunc.vecEvalJSON(input, output); err != nil { 1584 b.Fatal(err) 1585 } 1586 } 1587 case types.ETString: 1588 for i := 0; i < b.N; i++ { 1589 if err := baseFunc.vecEvalString(input, output); err != nil { 1590 b.Fatal(err) 1591 } 1592 } 1593 default: 1594 b.Fatal(fmt.Sprintf("evalType=%v is not supported", testCase.retEvalType)) 1595 } 1596 }) 1597 b.Run(baseFuncName+"-NonVecBuiltinFunc", func(b *testing.B) { 1598 b.ResetTimer() 1599 it := chunk.NewIterator4Chunk(input) 1600 switch testCase.retEvalType { 1601 case types.ETInt: 1602 for i := 0; i < b.N; i++ { 1603 output.Reset(testCase.retEvalType) 1604 for event := it.Begin(); event != it.End(); event = it.Next() { 1605 v, isNull, err := baseFunc.evalInt(event) 1606 if err != nil { 1607 b.Fatal(err) 1608 } 1609 if isNull { 1610 output.AppendNull() 1611 } else { 1612 output.AppendInt64(v) 1613 } 1614 } 1615 } 1616 case types.ETReal: 1617 for i := 0; i < b.N; i++ { 1618 output.Reset(testCase.retEvalType) 1619 for event := it.Begin(); event != it.End(); event = it.Next() { 1620 v, isNull, err := baseFunc.evalReal(event) 1621 if err != nil { 1622 b.Fatal(err) 1623 } 1624 if isNull { 1625 output.AppendNull() 1626 } else { 1627 output.AppendFloat64(v) 1628 } 1629 } 1630 } 1631 case types.ETDecimal: 1632 for i := 0; i < b.N; i++ { 1633 output.Reset(testCase.retEvalType) 1634 for event := it.Begin(); event != it.End(); event = it.Next() { 1635 v, isNull, err := baseFunc.evalDecimal(event) 1636 if err != nil { 1637 b.Fatal(err) 1638 } 1639 if isNull { 1640 output.AppendNull() 1641 } else { 1642 output.AppendMyDecimal(v) 1643 } 1644 } 1645 } 1646 case types.ETDatetime, types.ETTimestamp: 1647 for i := 0; i < b.N; i++ { 1648 output.Reset(testCase.retEvalType) 1649 for event := it.Begin(); event != it.End(); event = it.Next() { 1650 v, isNull, err := baseFunc.evalTime(event) 1651 if err != nil { 1652 b.Fatal(err) 1653 } 1654 if isNull { 1655 output.AppendNull() 1656 } else { 1657 output.AppendTime(v) 1658 } 1659 } 1660 } 1661 case types.ETDuration: 1662 for i := 0; i < b.N; i++ { 1663 output.Reset(testCase.retEvalType) 1664 for event := it.Begin(); event != it.End(); event = it.Next() { 1665 v, isNull, err := baseFunc.evalDuration(event) 1666 if err != nil { 1667 b.Fatal(err) 1668 } 1669 if isNull { 1670 output.AppendNull() 1671 } else { 1672 output.AppendDuration(v) 1673 } 1674 } 1675 } 1676 case types.ETJson: 1677 for i := 0; i < b.N; i++ { 1678 output.Reset(testCase.retEvalType) 1679 for event := it.Begin(); event != it.End(); event = it.Next() { 1680 v, isNull, err := baseFunc.evalJSON(event) 1681 if err != nil { 1682 b.Fatal(err) 1683 } 1684 if isNull { 1685 output.AppendNull() 1686 } else { 1687 output.AppendJSON(v) 1688 } 1689 } 1690 } 1691 case types.ETString: 1692 for i := 0; i < b.N; i++ { 1693 output.Reset(testCase.retEvalType) 1694 for event := it.Begin(); event != it.End(); event = it.Next() { 1695 v, isNull, err := baseFunc.evalString(event) 1696 if err != nil { 1697 b.Fatal(err) 1698 } 1699 if isNull { 1700 output.AppendNull() 1701 } else { 1702 output.AppendString(v) 1703 } 1704 } 1705 } 1706 default: 1707 b.Fatal(fmt.Sprintf("evalType=%v is not supported", testCase.retEvalType)) 1708 } 1709 }) 1710 } 1711 } 1712 } 1713 1714 func genVecEvalBool(numDefCauss int, defCausTypes, eTypes []types.EvalType) (CNFExprs, *chunk.Chunk) { 1715 gens := make([]dataGenerator, 0, len(eTypes)) 1716 for _, eType := range eTypes { 1717 if eType == types.ETString { 1718 gens = append(gens, &numStrGener{*newRangeInt64Gener(0, 10)}) 1719 } else { 1720 gens = append(gens, newDefaultGener(0.05, eType)) 1721 } 1722 } 1723 1724 ts := make([]types.EvalType, 0, numDefCauss) 1725 gs := make([]dataGenerator, 0, numDefCauss) 1726 fts := make([]*types.FieldType, 0, numDefCauss) 1727 randGen := newDefaultRandGen() 1728 for i := 0; i < numDefCauss; i++ { 1729 idx := randGen.Intn(len(eTypes)) 1730 if defCausTypes != nil { 1731 for j := range eTypes { 1732 if defCausTypes[i] == eTypes[j] { 1733 idx = j 1734 break 1735 } 1736 } 1737 } 1738 ts = append(ts, eTypes[idx]) 1739 gs = append(gs, gens[idx]) 1740 fts = append(fts, eType2FieldType(eTypes[idx])) 1741 } 1742 1743 input := chunk.New(fts, 1024, 1024) 1744 exprs := make(CNFExprs, 0, numDefCauss) 1745 for i := 0; i < numDefCauss; i++ { 1746 fillDeferredCauset(ts[i], input, i, vecExprBenchCase{geners: gs}) 1747 exprs = append(exprs, &DeferredCauset{Index: i, RetType: fts[i]}) 1748 } 1749 return exprs, input 1750 } 1751 1752 func generateRandomSel() []int { 1753 randGen := newDefaultRandGen() 1754 randGen.Seed(time.Now().UnixNano()) 1755 var sel []int 1756 count := 0 1757 // Use constant 256 to make it faster to generate randomly arranged sel slices 1758 num := randGen.Intn(256) + 1 1759 existed := make([]bool, 1024) 1760 for i := 0; i < 1024; i++ { 1761 existed[i] = false 1762 } 1763 for count < num { 1764 val := randGen.Intn(1024) 1765 if !existed[val] { 1766 existed[val] = true 1767 count++ 1768 } 1769 } 1770 for i := 0; i < 1024; i++ { 1771 if existed[i] { 1772 sel = append(sel, i) 1773 } 1774 } 1775 return sel 1776 } 1777 1778 func (s *testVectorizeSuite2) TestVecEvalBool(c *C) { 1779 ctx := mock.NewContext() 1780 eTypes := []types.EvalType{types.ETReal, types.ETDecimal, types.ETString, types.ETTimestamp, types.ETDatetime, types.ETDuration} 1781 for numDefCauss := 1; numDefCauss <= 5; numDefCauss++ { 1782 for round := 0; round < 16; round++ { 1783 exprs, input := genVecEvalBool(numDefCauss, nil, eTypes) 1784 selected, nulls, err := VecEvalBool(ctx, exprs, input, nil, nil) 1785 c.Assert(err, IsNil) 1786 it := chunk.NewIterator4Chunk(input) 1787 i := 0 1788 for event := it.Begin(); event != it.End(); event = it.Next() { 1789 ok, null, err := EvalBool(mock.NewContext(), exprs, event) 1790 c.Assert(err, IsNil) 1791 c.Assert(null, Equals, nulls[i]) 1792 c.Assert(ok, Equals, selected[i]) 1793 i++ 1794 } 1795 } 1796 } 1797 } 1798 1799 func BenchmarkVecEvalBool(b *testing.B) { 1800 ctx := mock.NewContext() 1801 selected := make([]bool, 0, 1024) 1802 nulls := make([]bool, 0, 1024) 1803 eTypes := []types.EvalType{types.ETInt, types.ETReal, types.ETDecimal, types.ETString, types.ETTimestamp, types.ETDatetime, types.ETDuration} 1804 tNames := []string{"int", "real", "decimal", "string", "timestamp", "datetime", "duration"} 1805 for numDefCauss := 1; numDefCauss <= 2; numDefCauss++ { 1806 typeCombination := make([]types.EvalType, numDefCauss) 1807 var combFunc func(nDefCauss int) 1808 combFunc = func(nDefCauss int) { 1809 if nDefCauss == 0 { 1810 name := "" 1811 for _, t := range typeCombination { 1812 for i := range eTypes { 1813 if t == eTypes[i] { 1814 name += tNames[t] + "/" 1815 } 1816 } 1817 } 1818 exprs, input := genVecEvalBool(numDefCauss, typeCombination, eTypes) 1819 b.Run("Vec-"+name, func(b *testing.B) { 1820 b.ResetTimer() 1821 for i := 0; i < b.N; i++ { 1822 _, _, err := VecEvalBool(ctx, exprs, input, selected, nulls) 1823 if err != nil { 1824 b.Fatal(err) 1825 } 1826 } 1827 }) 1828 b.Run("Event-"+name, func(b *testing.B) { 1829 b.ResetTimer() 1830 for i := 0; i < b.N; i++ { 1831 it := chunk.NewIterator4Chunk(input) 1832 for event := it.Begin(); event != it.End(); event = it.Next() { 1833 _, _, err := EvalBool(ctx, exprs, event) 1834 if err != nil { 1835 b.Fatal(err) 1836 } 1837 } 1838 } 1839 }) 1840 return 1841 } 1842 for _, eType := range eTypes { 1843 typeCombination[nDefCauss-1] = eType 1844 combFunc(nDefCauss - 1) 1845 } 1846 } 1847 1848 combFunc(numDefCauss) 1849 } 1850 } 1851 1852 func (s *testVectorizeSuite2) TestEventBasedFilterAndVectorizedFilter(c *C) { 1853 ctx := mock.NewContext() 1854 eTypes := []types.EvalType{types.ETInt, types.ETReal, types.ETDecimal, types.ETString, types.ETTimestamp, types.ETDatetime, types.ETDuration} 1855 for numDefCauss := 1; numDefCauss <= 5; numDefCauss++ { 1856 for round := 0; round < 16; round++ { 1857 exprs, input := genVecEvalBool(numDefCauss, nil, eTypes) 1858 it := chunk.NewIterator4Chunk(input) 1859 isNull := make([]bool, it.Len()) 1860 selected, nulls, err := rowBasedFilter(ctx, exprs, it, nil, isNull) 1861 c.Assert(err, IsNil) 1862 selected2, nulls2, err2 := vectorizedFilter(ctx, exprs, it, nil, isNull) 1863 c.Assert(err2, IsNil) 1864 length := it.Len() 1865 for i := 0; i < length; i++ { 1866 c.Assert(nulls2[i], Equals, nulls[i]) 1867 c.Assert(selected2[i], Equals, selected[i]) 1868 } 1869 } 1870 } 1871 } 1872 1873 func BenchmarkEventBasedFilterAndVectorizedFilter(b *testing.B) { 1874 ctx := mock.NewContext() 1875 selected := make([]bool, 0, 1024) 1876 nulls := make([]bool, 0, 1024) 1877 eTypes := []types.EvalType{types.ETInt, types.ETReal, types.ETDecimal, types.ETString, types.ETTimestamp, types.ETDatetime, types.ETDuration} 1878 tNames := []string{"int", "real", "decimal", "string", "timestamp", "datetime", "duration"} 1879 for numDefCauss := 1; numDefCauss <= 2; numDefCauss++ { 1880 typeCombination := make([]types.EvalType, numDefCauss) 1881 var combFunc func(nDefCauss int) 1882 combFunc = func(nDefCauss int) { 1883 if nDefCauss == 0 { 1884 name := "" 1885 for _, t := range typeCombination { 1886 for i := range eTypes { 1887 if t == eTypes[i] { 1888 name += tNames[t] + "/" 1889 } 1890 } 1891 } 1892 exprs, input := genVecEvalBool(numDefCauss, typeCombination, eTypes) 1893 it := chunk.NewIterator4Chunk(input) 1894 b.Run("Vec-"+name, func(b *testing.B) { 1895 b.ResetTimer() 1896 for i := 0; i < b.N; i++ { 1897 _, _, err := vectorizedFilter(ctx, exprs, it, selected, nulls) 1898 if err != nil { 1899 b.Fatal(err) 1900 } 1901 } 1902 }) 1903 b.Run("Event-"+name, func(b *testing.B) { 1904 b.ResetTimer() 1905 for i := 0; i < b.N; i++ { 1906 _, _, err := rowBasedFilter(ctx, exprs, it, selected, nulls) 1907 if err != nil { 1908 b.Fatal(err) 1909 } 1910 } 1911 }) 1912 return 1913 } 1914 for _, eType := range eTypes { 1915 typeCombination[nDefCauss-1] = eType 1916 combFunc(nDefCauss - 1) 1917 } 1918 } 1919 combFunc(numDefCauss) 1920 } 1921 1922 // Add special case to prove when some calculations are added, 1923 // the vectorizedFilter for int types will be more faster than rowBasedFilter. 1924 funcName := ast.Least 1925 testCase := vecExprBenchCase{retEvalType: types.ETInt, childrenTypes: []types.EvalType{types.ETInt, types.ETInt}} 1926 expr, _, input, _ := genVecExprBenchCase(ctx, funcName, testCase) 1927 it := chunk.NewIterator4Chunk(input) 1928 1929 b.Run("Vec-special case", func(b *testing.B) { 1930 b.ResetTimer() 1931 for i := 0; i < b.N; i++ { 1932 _, _, err := vectorizedFilter(ctx, []Expression{expr}, it, selected, nulls) 1933 if err != nil { 1934 panic(err) 1935 } 1936 } 1937 }) 1938 b.Run("Event-special case", func(b *testing.B) { 1939 b.ResetTimer() 1940 for i := 0; i < b.N; i++ { 1941 _, _, err := rowBasedFilter(ctx, []Expression{expr}, it, selected, nulls) 1942 if err != nil { 1943 panic(err) 1944 } 1945 } 1946 }) 1947 } 1948 1949 func (s *testVectorizeSuite2) TestVectorizedFilterConsiderNull(c *C) { 1950 ctx := mock.NewContext() 1951 dafaultEnableVectorizedExpressionVar := ctx.GetStochastikVars().EnableVectorizedExpression 1952 eTypes := []types.EvalType{types.ETInt, types.ETReal, types.ETDecimal, types.ETString, types.ETTimestamp, types.ETDatetime, types.ETDuration} 1953 for numDefCauss := 1; numDefCauss <= 5; numDefCauss++ { 1954 for round := 0; round < 16; round++ { 1955 exprs, input := genVecEvalBool(numDefCauss, nil, eTypes) 1956 it := chunk.NewIterator4Chunk(input) 1957 isNull := make([]bool, it.Len()) 1958 ctx.GetStochastikVars().EnableVectorizedExpression = false 1959 selected, nulls, err := VectorizedFilterConsiderNull(ctx, exprs, it, nil, isNull) 1960 c.Assert(err, IsNil) 1961 ctx.GetStochastikVars().EnableVectorizedExpression = true 1962 selected2, nulls2, err2 := VectorizedFilterConsiderNull(ctx, exprs, it, nil, isNull) 1963 c.Assert(err2, IsNil) 1964 length := it.Len() 1965 for i := 0; i < length; i++ { 1966 c.Assert(nulls2[i], Equals, nulls[i]) 1967 c.Assert(selected2[i], Equals, selected[i]) 1968 } 1969 1970 // add test which sel is not nil 1971 randomSel := generateRandomSel() 1972 input.SetSel(randomSel) 1973 it2 := chunk.NewIterator4Chunk(input) 1974 isNull = isNull[:0] 1975 ctx.GetStochastikVars().EnableVectorizedExpression = false 1976 selected3, nulls, err := VectorizedFilterConsiderNull(ctx, exprs, it2, nil, isNull) 1977 c.Assert(err, IsNil) 1978 ctx.GetStochastikVars().EnableVectorizedExpression = true 1979 selected4, nulls2, err2 := VectorizedFilterConsiderNull(ctx, exprs, it2, nil, isNull) 1980 c.Assert(err2, IsNil) 1981 for i := 0; i < length; i++ { 1982 c.Assert(nulls2[i], Equals, nulls[i]) 1983 c.Assert(selected4[i], Equals, selected3[i]) 1984 } 1985 1986 unselected := make([]bool, length) 1987 // unselected[i] == false means that the i-th event is selected 1988 for i := 0; i < length; i++ { 1989 unselected[i] = true 1990 } 1991 for _, idx := range randomSel { 1992 unselected[idx] = false 1993 } 1994 for i := range selected2 { 1995 if selected2[i] && unselected[i] { 1996 selected2[i] = false 1997 } 1998 } 1999 for i := 0; i < length; i++ { 2000 c.Assert(selected2[i], Equals, selected4[i]) 2001 } 2002 } 2003 } 2004 ctx.GetStochastikVars().EnableVectorizedExpression = dafaultEnableVectorizedExpressionVar 2005 }