github.com/mitranim/sqlb@v0.7.2/t_bench_test.go (about) 1 package sqlb 2 3 import ( 4 r "reflect" 5 "testing" 6 ) 7 8 func Benchmark_delete_ast_create(b *testing.B) { 9 for range counter(b.N) { 10 _ = benchDeleteAst() 11 } 12 } 13 14 //go:noinline 15 func benchDeleteAst() Expr { 16 return qDeleteAst(`some_table`, External{}) 17 } 18 19 func qDeleteAst(from Ident, where any) Expr { 20 return Delete{from, where} 21 } 22 23 func Benchmark_delete_ast_append(b *testing.B) { 24 for range counter(b.N) { 25 benchDeleteAstAppend() 26 } 27 } 28 29 var exprDeleteAst = benchDeleteAst() 30 31 //go:noinline 32 func benchDeleteAstAppend() { 33 exprDeleteAst.AppendExpr(hugeBui.Get()) 34 } 35 36 func Benchmark_delete_ast_reify(b *testing.B) { 37 for range counter(b.N) { 38 benchDeleteAstReify() 39 } 40 } 41 42 //go:noinline 43 func benchDeleteAstReify() { 44 bui := hugeBui 45 bui.Expr(exprDeleteAst) 46 bui.Reify() 47 } 48 49 func Benchmark_delete_text_create(b *testing.B) { 50 for range counter(b.N) { 51 _ = benchDeleteText() 52 } 53 } 54 55 //go:noinline 56 func benchDeleteText() Expr { 57 return qDeleteText(`some_table`, External{}) 58 } 59 60 func qDeleteText(ident Ident, where any) Expr { 61 return StrQ{`delete from :ident where :where returning *`, Dict{ 62 `ident`: ident, 63 `where`: And{where}, 64 }} 65 } 66 67 func Benchmark_delete_text_append(b *testing.B) { 68 for range counter(b.N) { 69 benchDeleteTextAppend() 70 } 71 } 72 73 var exprDeleteText = benchDeleteText() 74 75 //go:noinline 76 func benchDeleteTextAppend() { 77 exprDeleteText.AppendExpr(hugeBui.Get()) 78 } 79 80 func Benchmark_delete_text_reify(b *testing.B) { 81 for range counter(b.N) { 82 benchDeleteTextReify() 83 } 84 } 85 86 //go:noinline 87 func benchDeleteTextReify() { 88 bui := hugeBui 89 bui.Expr(exprDeleteText) 90 bui.Reify() 91 } 92 93 func Benchmark_struct_walk(b *testing.B) { 94 for range counter(b.N) { 95 benchStructWalk() 96 } 97 } 98 99 //go:noinline 100 func benchStructWalk() { tCols() } 101 102 func Benchmark_TypeColsDeep(b *testing.B) { 103 for range counter(b.N) { 104 benchLoadCols() 105 } 106 } 107 108 var outerType = r.TypeOf((*Outer)(nil)).Elem() 109 110 //go:noinline 111 func benchLoadCols() { TypeColsDeep(outerType) } 112 113 func Benchmark_loadStructDbFields(b *testing.B) { 114 for range counter(b.N) { 115 benchLoadColumnFields() 116 } 117 } 118 119 //go:noinline 120 func benchLoadColumnFields() { loadStructDbFields(outerType) } 121 122 func Benchmark_loadStructPathMap(b *testing.B) { 123 for range counter(b.N) { 124 benchLoadStructPathMap() 125 } 126 } 127 128 //go:noinline 129 func benchLoadStructPathMap() { loadStructPathMap(outerType) } 130 131 func Benchmark_huge_query_wrap(b *testing.B) { 132 for range counter(b.N) { 133 _ = benchHugeQueryWrap() 134 } 135 } 136 137 //go:noinline 138 func benchHugeQueryWrap() StrQ { 139 return DictQ(`:one`, Dict{`one`: hugeQueryUnwrapped}) 140 } 141 142 var hugeQueryUnwrapped = DictQ(hugeQuery, hugeQueryArgs) 143 144 func Benchmark_huge_query_append_unwrapped(b *testing.B) { 145 for range counter(b.N) { 146 benchHugeQueryAppendUnwrapped() 147 } 148 } 149 150 //go:noinline 151 func benchHugeQueryAppendUnwrapped() { 152 hugeQueryUnwrapped.AppendExpr(hugeBui.Get()) 153 } 154 155 func Benchmark_huge_query_append_wrapped(b *testing.B) { 156 for range counter(b.N) { 157 benchHugeQueryAppendWrapped() 158 } 159 } 160 161 var hugeQueryWrapped = benchHugeQueryWrap() 162 163 //go:noinline 164 func benchHugeQueryAppendWrapped() { 165 hugeQueryWrapped.AppendExpr(hugeBui.Get()) 166 } 167 168 func Benchmark_make_list(b *testing.B) { 169 for range counter(b.N) { 170 benchMakeList() 171 } 172 } 173 174 //go:noinline 175 func benchMakeList() ArgDict { 176 list := make(List, 24) 177 for ind := range list { 178 list[ind] = (ind + 1) * 10 179 } 180 return list 181 } 182 183 func Benchmark_make_dict(b *testing.B) { 184 for range counter(b.N) { 185 benchMakeDict() 186 } 187 } 188 189 //go:noinline 190 func benchMakeDict() ArgDict { 191 return Dict{ 192 `Key_c603c58746a69833a1528050c33d`: `val_e1436c61440383a80ebdc245b930`, 193 `Key_abfbb9e94e4093a47683e8ef606b`: `val_a6108ccd40789cecf4da1052c5ae`, 194 `Key_907b548d45948a206907ed9c9097`: `val_9271789147789ecb2beb11c97a78`, 195 `Key_5ee2513a41a88d173cd53d389c14`: `val_2b6205fb4bf882ab65f3795b2384`, 196 `Key_0ac8b89b46bba5d4d076e71d6232`: `val_226b2c3a4c5591084d3a120de2d8`, 197 `Key_b754f88b42fcbd6c30e3bb544909`: `val_9c639ea74d099446ec3aa2a736a8`, 198 `Key_e52daa684071891a1dae084bfd00`: `val_71fc2d114b2aaa3b5c1c399d28f6`, 199 `Key_3106dc324be4b3ff5d477e71c593`: `val_9183d36e4b53a5e2b26ca950a721`, 200 `Key_a7b558a54d178bdb6fcf3368939b`: `val_f0bc980a408c81a959168aa8aabc`, 201 `Key_1622da954c8a8f6fec82e6fd3c34`: `val_4afe6fa84722a214e4e777aa6bcf`, 202 `Key_fa3892644f1392aee8e66b799b3f`: `val_c45ce5ec46b7809d5df5cd1c815b`, 203 `Key_b9aa15254438b0b7a32489947c50`: `val_6b119aad4bc280a3dfa675fe88a5`, 204 205 `Key_ce59b8e14f77b6e6e9cd28cecacd`: `val_c76bd35c42d49ccb4408f92fb222`, 206 `Key_87819a034834a3530b8255e76e4d`: `val_a185f0a946e894d1628bb98b673e`, 207 `Key_c31042674737a95d1cba33b61687`: `val_02bae4964cfa9ebd23b5d3f57ee6`, 208 `Key_7bc7a0d346c2b87e3110b2d192d3`: `val_2208de3a476299877d36f149ab94`, 209 `Key_3b17f4454d44abbbeb2eb5b61235`: `val_dfb68e4d459aa5c649dcb07e0bfb`, 210 `Key_83e52b714a9d8a0ba6dd87658acf`: `val_2ec2ca5046038e80cfa3cb23dff2`, 211 `Key_82c96b4d4965a08fa6735e973caa`: `val_fae699f449a1aaf138b1ae2bb9b0`, 212 `Key_7580ec1f4d42a7aafddf4f818b97`: `val_fc6b97924798b1b790cfb6e31750`, 213 `Key_bc03a581465c873ceea04027d6ab`: `val_ab22ce72453cb2577aa731dae72c`, 214 `Key_dcfa83ed4be89cf05d5e3eba6f2a`: `val_b773e8ce401c8313b1400b973fa1`, 215 `Key_2bc5f64447879c1152ae9b904718`: `val_e9d6438d42339e4c62db260c458b`, 216 `Key_4f0e9d9b4d1ea77c510337ae6c2a`: `val_60a4b1bf406f98826c706ab153d1`, 217 } 218 } 219 220 func Benchmark_make_struct_dict(b *testing.B) { 221 for range counter(b.N) { 222 benchMakeStructDict() 223 } 224 } 225 226 //go:noinline 227 func benchMakeStructDict() ArgDict { 228 return StructDict{r.ValueOf(BenchStructDict{ 229 Key_c603c58746a69833a1528050c33d: `val_e1436c61440383a80ebdc245b930`, 230 Key_abfbb9e94e4093a47683e8ef606b: `val_a6108ccd40789cecf4da1052c5ae`, 231 Key_907b548d45948a206907ed9c9097: `val_9271789147789ecb2beb11c97a78`, 232 Key_5ee2513a41a88d173cd53d389c14: `val_2b6205fb4bf882ab65f3795b2384`, 233 Key_0ac8b89b46bba5d4d076e71d6232: `val_226b2c3a4c5591084d3a120de2d8`, 234 Key_b754f88b42fcbd6c30e3bb544909: `val_9c639ea74d099446ec3aa2a736a8`, 235 Key_e52daa684071891a1dae084bfd00: `val_71fc2d114b2aaa3b5c1c399d28f6`, 236 Key_3106dc324be4b3ff5d477e71c593: `val_9183d36e4b53a5e2b26ca950a721`, 237 Key_a7b558a54d178bdb6fcf3368939b: `val_f0bc980a408c81a959168aa8aabc`, 238 Key_1622da954c8a8f6fec82e6fd3c34: `val_4afe6fa84722a214e4e777aa6bcf`, 239 Key_fa3892644f1392aee8e66b799b3f: `val_c45ce5ec46b7809d5df5cd1c815b`, 240 Key_b9aa15254438b0b7a32489947c50: `val_6b119aad4bc280a3dfa675fe88a5`, 241 })} 242 } 243 244 type BenchStructDict struct { 245 Key_c603c58746a69833a1528050c33d any 246 Key_abfbb9e94e4093a47683e8ef606b any 247 Key_907b548d45948a206907ed9c9097 any 248 Key_5ee2513a41a88d173cd53d389c14 any 249 Key_0ac8b89b46bba5d4d076e71d6232 any 250 Key_b754f88b42fcbd6c30e3bb544909 any 251 Key_e52daa684071891a1dae084bfd00 any 252 Key_3106dc324be4b3ff5d477e71c593 any 253 Key_a7b558a54d178bdb6fcf3368939b any 254 Key_1622da954c8a8f6fec82e6fd3c34 any 255 Key_fa3892644f1392aee8e66b799b3f any 256 Key_b9aa15254438b0b7a32489947c50 any 257 } 258 259 func (self BenchStructDict) Key_ce59b8e14f77b6e6e9cd28cecacd() string { 260 return `val_c76bd35c42d49ccb4408f92fb222` 261 } 262 263 func (self BenchStructDict) Key_87819a034834a3530b8255e76e4d() string { 264 return `val_a185f0a946e894d1628bb98b673e` 265 } 266 267 func (self BenchStructDict) Key_c31042674737a95d1cba33b61687() string { 268 return `val_02bae4964cfa9ebd23b5d3f57ee6` 269 } 270 271 func (self BenchStructDict) Key_7bc7a0d346c2b87e3110b2d192d3() string { 272 return `val_2208de3a476299877d36f149ab94` 273 } 274 275 func (self BenchStructDict) Key_3b17f4454d44abbbeb2eb5b61235() string { 276 return `val_dfb68e4d459aa5c649dcb07e0bfb` 277 } 278 279 func (self BenchStructDict) Key_83e52b714a9d8a0ba6dd87658acf() string { 280 return `val_2ec2ca5046038e80cfa3cb23dff2` 281 } 282 283 func (self BenchStructDict) Key_82c96b4d4965a08fa6735e973caa() string { 284 return `val_fae699f449a1aaf138b1ae2bb9b0` 285 } 286 287 func (self BenchStructDict) Key_7580ec1f4d42a7aafddf4f818b97() string { 288 return `val_fc6b97924798b1b790cfb6e31750` 289 } 290 291 func (self BenchStructDict) Key_bc03a581465c873ceea04027d6ab() string { 292 return `val_ab22ce72453cb2577aa731dae72c` 293 } 294 295 func (self BenchStructDict) Key_dcfa83ed4be89cf05d5e3eba6f2a() string { 296 return `val_b773e8ce401c8313b1400b973fa1` 297 } 298 299 func (self BenchStructDict) Key_2bc5f64447879c1152ae9b904718() string { 300 return `val_e9d6438d42339e4c62db260c458b` 301 } 302 303 func (self BenchStructDict) Key_4f0e9d9b4d1ea77c510337ae6c2a() string { 304 return `val_60a4b1bf406f98826c706ab153d1` 305 } 306 307 func Benchmark_list_access(b *testing.B) { 308 list := benchList 309 benchTestListAccess(b, list) 310 b.ResetTimer() 311 312 for range counter(b.N) { 313 benchListAccess(list) 314 } 315 } 316 317 var benchList = benchMakeList() 318 319 func benchTestListAccess(t testing.TB, list ArgDict) { 320 test := func(key int, expVal any, expOk bool) { 321 t.Helper() 322 val, ok := list.GotOrdinal(key) 323 eq(t, expVal, val) 324 eq(t, expOk, ok) 325 } 326 327 test(-1, nil, false) 328 test(0, 10, true) 329 test(1, 20, true) 330 test(2, 30, true) 331 test(3, 40, true) 332 test(4, 50, true) 333 test(5, 60, true) 334 test(6, 70, true) 335 test(7, 80, true) 336 test(8, 90, true) 337 test(9, 100, true) 338 test(10, 110, true) 339 test(11, 120, true) 340 test(12, 130, true) 341 test(13, 140, true) 342 test(14, 150, true) 343 test(15, 160, true) 344 test(16, 170, true) 345 test(17, 180, true) 346 test(18, 190, true) 347 test(19, 200, true) 348 test(20, 210, true) 349 test(21, 220, true) 350 test(22, 230, true) 351 test(23, 240, true) 352 test(24, nil, false) 353 } 354 355 //go:noinline 356 func benchListAccess(list ArgDict) { 357 list.GotOrdinal(0) 358 list.GotOrdinal(1) 359 list.GotOrdinal(2) 360 list.GotOrdinal(3) 361 list.GotOrdinal(4) 362 list.GotOrdinal(5) 363 list.GotOrdinal(6) 364 list.GotOrdinal(7) 365 list.GotOrdinal(8) 366 list.GotOrdinal(9) 367 list.GotOrdinal(10) 368 list.GotOrdinal(11) 369 list.GotOrdinal(12) 370 list.GotOrdinal(13) 371 list.GotOrdinal(14) 372 list.GotOrdinal(15) 373 list.GotOrdinal(16) 374 list.GotOrdinal(17) 375 list.GotOrdinal(18) 376 list.GotOrdinal(19) 377 list.GotOrdinal(20) 378 list.GotOrdinal(21) 379 list.GotOrdinal(22) 380 list.GotOrdinal(23) 381 } 382 383 func Benchmark_dict_access(b *testing.B) { 384 for range counter(b.N) { 385 benchDictAccess(benchDict) 386 } 387 } 388 389 var benchDict = benchMakeDict() 390 391 func Benchmark_struct_dict_access(b *testing.B) { 392 for range counter(b.N) { 393 benchDictAccess(benchStructDict) 394 } 395 } 396 397 var benchStructDict = benchMakeStructDict() 398 399 //go:noinline 400 func benchDictAccess(dict ArgDict) { 401 dict.GotNamed(`Key_c603c58746a69833a1528050c33d`) 402 dict.GotNamed(`Key_abfbb9e94e4093a47683e8ef606b`) 403 dict.GotNamed(`Key_907b548d45948a206907ed9c9097`) 404 dict.GotNamed(`Key_5ee2513a41a88d173cd53d389c14`) 405 dict.GotNamed(`Key_0ac8b89b46bba5d4d076e71d6232`) 406 dict.GotNamed(`Key_b754f88b42fcbd6c30e3bb544909`) 407 dict.GotNamed(`Key_e52daa684071891a1dae084bfd00`) 408 dict.GotNamed(`Key_3106dc324be4b3ff5d477e71c593`) 409 dict.GotNamed(`Key_a7b558a54d178bdb6fcf3368939b`) 410 dict.GotNamed(`Key_1622da954c8a8f6fec82e6fd3c34`) 411 dict.GotNamed(`Key_fa3892644f1392aee8e66b799b3f`) 412 dict.GotNamed(`Key_b9aa15254438b0b7a32489947c50`) 413 414 dict.GotNamed(`Key_ce59b8e14f77b6e6e9cd28cecacd`) 415 dict.GotNamed(`Key_87819a034834a3530b8255e76e4d`) 416 dict.GotNamed(`Key_c31042674737a95d1cba33b61687`) 417 dict.GotNamed(`Key_7bc7a0d346c2b87e3110b2d192d3`) 418 dict.GotNamed(`Key_3b17f4454d44abbbeb2eb5b61235`) 419 dict.GotNamed(`Key_83e52b714a9d8a0ba6dd87658acf`) 420 dict.GotNamed(`Key_82c96b4d4965a08fa6735e973caa`) 421 dict.GotNamed(`Key_7580ec1f4d42a7aafddf4f818b97`) 422 dict.GotNamed(`Key_bc03a581465c873ceea04027d6ab`) 423 dict.GotNamed(`Key_dcfa83ed4be89cf05d5e3eba6f2a`) 424 dict.GotNamed(`Key_2bc5f64447879c1152ae9b904718`) 425 dict.GotNamed(`Key_4f0e9d9b4d1ea77c510337ae6c2a`) 426 } 427 428 func Benchmark_bui_expr_alloc(b *testing.B) { 429 { 430 benchBuiExprAlloc() 431 tHugeBuiEmpty(b) 432 } 433 b.ResetTimer() 434 435 for range counter(b.N) { 436 benchBuiExprAlloc() 437 } 438 } 439 440 //go:noinline 441 func benchBuiExprAlloc() { 442 bui := hugeBui 443 var expr Eq 444 // Go defect: this allocates and uses dynamic dispatch, even though it should 445 // be possible to specialize the code to avoid both (Go 1.17). 446 bui.Expr(&expr) 447 } 448 449 func Benchmark_bui_expr_zero_alloc(b *testing.B) { 450 { 451 benchBuiExprZeroAlloc() 452 tHugeBuiEmpty(b) 453 } 454 b.ResetTimer() 455 456 for range counter(b.N) { 457 benchBuiExprZeroAlloc() 458 } 459 } 460 461 //go:noinline 462 func benchBuiExprZeroAlloc() { 463 bui := hugeBui 464 var expr Eq 465 bui.Set(expr.AppendExpr(bui.Get())) 466 } 467 468 func Benchmark_Cond_AppendExpr(b *testing.B) { 469 for range counter(b.N) { 470 benchCondAppendExpr() 471 } 472 } 473 474 var benchCond = Cond{``, ``, External{}} 475 476 //go:noinline 477 func benchCondAppendExpr() { 478 benchCond.AppendExpr(hugeBui.Get()) 479 } 480 481 func Benchmark_huge_query_preparse(b *testing.B) { 482 for range counter(b.N) { 483 benchHugeQueryPreparse() 484 } 485 } 486 487 //go:noinline 488 func benchHugeQueryPreparse() Prep { 489 prep := Prep{Source: hugeQuery} 490 prep.Parse() 491 return prep 492 } 493 494 func Benchmark_huge_query_append_preparsed(b *testing.B) { 495 for range counter(b.N) { 496 benchHugeQueryAppendPreparsed() 497 } 498 } 499 500 var hugePrep = Preparse(hugeQuery) 501 502 //go:noinline 503 func benchHugeQueryAppendPreparsed() { 504 text, args := hugeBui.Get() 505 hugePrep.AppendParamExpr(text, args, hugeQueryArgs) 506 } 507 508 func Benchmark_error_make(b *testing.B) { 509 for range counter(b.N) { 510 _ = benchErrorMake() 511 } 512 } 513 514 var benchErr = benchErrorMake() 515 516 const benchErrCause = ErrStr(`some cause`) 517 518 //go:noinline 519 func benchErrorMake() error { 520 return ErrInternal{Err{`doing something`, benchErrCause}} 521 } 522 523 func Benchmark_error_format(b *testing.B) { 524 for range counter(b.N) { 525 benchErrorFormat() 526 } 527 } 528 529 //go:noinline 530 func benchErrorFormat() { 531 _ = benchErr.Error() 532 } 533 534 func Benchmark_loadPrep(b *testing.B) { 535 for range counter(b.N) { 536 benchLoadPrep() 537 } 538 } 539 540 //go:noinline 541 func benchLoadPrep() { Preparse(hugeQuery) } 542 543 func Benchmark_dict_to_iface_alloc(b *testing.B) { 544 dict := benchMakeDict().(Dict) 545 b.ResetTimer() 546 for range counter(b.N) { 547 benchDictToIfaceAlloc(dict) 548 } 549 } 550 551 //go:noinline 552 func benchDictToIfaceAlloc(val Dict) { nop(val) } 553 554 var nop = func(ArgDict) {} 555 556 func Benchmark_parse_ords(b *testing.B) { 557 for range counter(b.N) { 558 benchParseOrds() 559 } 560 } 561 562 //go:noinline 563 func benchParseOrds() { 564 parser := benchParserOrds 565 try(parser.ParseSlice(benchOrderingStrings)) 566 } 567 568 var benchParserOrds = ParserOrds{ 569 Ords: make(Ords, 0, len(benchOrderingStrings)), 570 ParseOpt: ParseOpt{ 571 Type: r.TypeOf((*External)(nil)).Elem(), 572 }, 573 } 574 575 var benchOrderingStrings = []string{ 576 `externalId`, 577 `externalName desc`, 578 `externalInternal.internalId nulls last`, 579 `externalInternal.internalName desc nulls first`, 580 } 581 582 func Benchmark_StructInsert_AppendExpr(b *testing.B) { 583 expr := StructInsert{testOuter} 584 b.ResetTimer() 585 586 for range counter(b.N) { 587 expr.AppendExpr(hugeBui.Get()) 588 } 589 } 590 591 func Benchmark_StructValues_AppendExpr(b *testing.B) { 592 expr := StructValues{testOuter} 593 b.ResetTimer() 594 595 for range counter(b.N) { 596 expr.AppendExpr(hugeBui.Get()) 597 } 598 }