go.chromium.org/luci@v0.0.0-20240309015107-7cdc2e660f33/analysis/internal/changepoints/inputbuffer/input_segment_test.go (about) 1 // Copyright 2023 The LUCI Authors. 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 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package inputbuffer 16 17 import ( 18 "testing" 19 "time" 20 21 "google.golang.org/protobuf/types/known/timestamppb" 22 23 cpb "go.chromium.org/luci/analysis/internal/changepoints/proto" 24 25 . "github.com/smartystreets/goconvey/convey" 26 . "go.chromium.org/luci/common/testing/assertions" 27 ) 28 29 func TestSegmentizeInputBuffer(t *testing.T) { 30 Convey("Segmentize input buffer", t, func() { 31 Convey("No change point", func() { 32 var ( 33 positions = []int{1, 2, 3, 4, 5, 6} 34 total = []int{1, 2, 1, 2, 1, 2} 35 hasUnexpected = []int{0, 1, 0, 2, 0, 0} 36 ) 37 ib := genInputBuffer(10, 200, Verdicts(positions, total, hasUnexpected)) 38 cps := []ChangePoint{} 39 40 var merged []PositionVerdict 41 ib.MergeBuffer(&merged) 42 sib := ib.Segmentize(merged, cps) 43 ibSegments := sib.Segments 44 So(len(ibSegments), ShouldEqual, 1) 45 So(ibSegments[0], ShouldResembleProto, &Segment{ 46 StartIndex: 0, 47 EndIndex: 5, 48 HasStartChangepoint: false, 49 StartPosition: 1, 50 EndPosition: 6, 51 StartHour: timestamppb.New(time.Unix(3600, 0)), 52 EndHour: timestamppb.New(time.Unix(6*3600, 0)), 53 Counts: &cpb.Counts{ 54 TotalResults: 9, 55 UnexpectedResults: 3, 56 TotalRuns: 9, 57 UnexpectedUnretriedRuns: 3, 58 TotalVerdicts: 6, 59 FlakyVerdicts: 1, 60 UnexpectedVerdicts: 1, 61 ExpectedPassedResults: 6, 62 UnexpectedFailedResults: 3, 63 }, 64 MostRecentUnexpectedResultHourAllVerdicts: timestamppb.New(time.Unix(4*3600, 0)), 65 }) 66 }) 67 68 Convey("With change points and retries", func() { 69 var ( 70 positions = []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12} 71 total = []int{1, 1, 1, 2, 2, 2, 2, 2, 2, 1, 1, 1} 72 hasUnexpected = []int{0, 0, 0, 2, 2, 2, 2, 2, 2, 1, 1, 1} 73 retries = []int{0, 0, 0, 2, 2, 2, 2, 2, 2, 0, 0, 0} 74 unexpectedAfterRetry = []int{0, 0, 0, 2, 2, 2, 0, 0, 0, 0, 0, 0} 75 ) 76 ib := genInputbufferWithRetries(10, 200, positions, total, hasUnexpected, retries, unexpectedAfterRetry) 77 cps := []ChangePoint{ 78 { 79 NominalIndex: 3, 80 LowerBound99ThIndex: 2, 81 UpperBound99ThIndex: 4, 82 }, 83 { 84 NominalIndex: 6, 85 LowerBound99ThIndex: 5, 86 UpperBound99ThIndex: 7, 87 }, 88 { 89 NominalIndex: 9, 90 LowerBound99ThIndex: 8, 91 UpperBound99ThIndex: 10, 92 }, 93 } 94 var merged []PositionVerdict 95 ib.MergeBuffer(&merged) 96 sib := ib.Segmentize(merged, cps) 97 ibSegments := sib.Segments 98 So(len(ibSegments), ShouldEqual, 4) 99 So(ibSegments[0], ShouldResembleProto, &Segment{ 100 StartIndex: 0, 101 EndIndex: 2, 102 HasStartChangepoint: false, 103 StartPosition: 1, 104 EndPosition: 3, 105 StartHour: timestamppb.New(time.Unix(3600, 0)), 106 EndHour: timestamppb.New(time.Unix(3*3600, 0)), 107 Counts: &cpb.Counts{ 108 TotalResults: 3, 109 TotalRuns: 3, 110 TotalVerdicts: 3, 111 ExpectedPassedResults: 3, 112 }, 113 }) 114 115 So(ibSegments[1], ShouldResembleProto, &Segment{ 116 StartIndex: 3, 117 EndIndex: 5, 118 HasStartChangepoint: true, 119 StartPosition: 4, 120 StartPositionLowerBound99Th: 3, 121 StartPositionUpperBound99Th: 5, 122 EndPosition: 6, 123 StartHour: timestamppb.New(time.Unix(4*3600, 0)), 124 EndHour: timestamppb.New(time.Unix(6*3600, 0)), 125 Counts: &cpb.Counts{ 126 TotalResults: 12, 127 UnexpectedResults: 12, 128 TotalRuns: 6, 129 UnexpectedAfterRetryRuns: 6, 130 TotalVerdicts: 3, 131 UnexpectedVerdicts: 3, 132 UnexpectedFailedResults: 6, 133 UnexpectedCrashedResults: 6, 134 }, 135 MostRecentUnexpectedResultHourAllVerdicts: timestamppb.New(time.Unix(6*3600, 0)), 136 }) 137 138 So(ibSegments[2], ShouldResembleProto, &Segment{ 139 StartIndex: 6, 140 EndIndex: 8, 141 HasStartChangepoint: true, 142 StartPosition: 7, 143 StartPositionLowerBound99Th: 6, 144 StartPositionUpperBound99Th: 8, 145 EndPosition: 9, 146 StartHour: timestamppb.New(time.Unix(7*3600, 0)), 147 EndHour: timestamppb.New(time.Unix(9*3600, 0)), 148 Counts: &cpb.Counts{ 149 TotalResults: 12, 150 UnexpectedResults: 6, 151 TotalRuns: 6, 152 FlakyRuns: 6, 153 TotalVerdicts: 3, 154 FlakyVerdicts: 3, 155 ExpectedPassedResults: 6, 156 UnexpectedFailedResults: 6, 157 }, 158 MostRecentUnexpectedResultHourAllVerdicts: timestamppb.New(time.Unix(9*3600, 0)), 159 }) 160 161 So(ibSegments[3], ShouldResembleProto, &Segment{ 162 StartIndex: 9, 163 EndIndex: 11, 164 HasStartChangepoint: true, 165 StartPosition: 10, 166 StartPositionLowerBound99Th: 9, 167 StartPositionUpperBound99Th: 11, 168 EndPosition: 12, 169 StartHour: timestamppb.New(time.Unix(10*3600, 0)), 170 EndHour: timestamppb.New(time.Unix(12*3600, 0)), 171 Counts: &cpb.Counts{ 172 TotalResults: 3, 173 UnexpectedResults: 3, 174 TotalRuns: 3, 175 UnexpectedUnretriedRuns: 3, 176 TotalVerdicts: 3, 177 UnexpectedVerdicts: 3, 178 UnexpectedFailedResults: 3, 179 }, 180 MostRecentUnexpectedResultHourAllVerdicts: timestamppb.New(time.Unix(12*3600, 0)), 181 }) 182 }) 183 }) 184 } 185 186 func TestEvictSegments(t *testing.T) { 187 Convey("Not evict segment", t, func() { 188 ib := genInputBuffer(100, 2000, simpleVerdicts(100, 1, []int{})) 189 segments := []*Segment{ 190 { 191 StartIndex: 0, 192 EndIndex: 99, 193 Counts: &cpb.Counts{ 194 TotalResults: 100, 195 TotalRuns: 100, 196 TotalVerdicts: 100, 197 }, 198 StartPosition: 1, 199 EndPosition: 100, 200 }, 201 } 202 sib := &SegmentedInputBuffer{ 203 InputBuffer: ib, 204 Segments: segments, 205 } 206 evicted := sib.EvictSegments() 207 remaining := sib.Segments 208 So(len(evicted), ShouldEqual, 0) 209 So(len(remaining), ShouldEqual, 1) 210 So(ib.IsColdBufferDirty, ShouldBeFalse) 211 So(remaining[0], ShouldResembleProto, segments[0]) 212 }) 213 214 Convey("Evict finalizing segment", t, func() { 215 ib := genInputBuffer(100, 2000, simpleVerdicts(2100, 1, []int{50, 1900})) 216 segments := []*Segment{ 217 { 218 StartIndex: 0, 219 EndIndex: 2049, 220 Counts: &cpb.Counts{ 221 TotalResults: 2050, 222 TotalRuns: 2050, 223 TotalVerdicts: 2050, 224 ExpectedPassedResults: 2050, 225 }, 226 HasStartChangepoint: false, 227 StartHour: timestamppb.New(time.Unix(1*3600, 0)), 228 StartPosition: 1, 229 EndHour: timestamppb.New(time.Unix(2050*3600, 0)), 230 EndPosition: 2050, 231 }, 232 { 233 StartIndex: 2050, 234 EndIndex: 2099, 235 Counts: &cpb.Counts{ 236 TotalResults: 50, 237 TotalRuns: 50, 238 TotalVerdicts: 50, 239 ExpectedPassedResults: 50, 240 }, 241 HasStartChangepoint: true, 242 StartHour: timestamppb.New(time.Unix(2051*3600, 0)), 243 StartPosition: 2051, 244 EndHour: timestamppb.New(time.Unix(2100*3600, 0)), 245 EndPosition: 2100, 246 }, 247 } 248 sib := &SegmentedInputBuffer{ 249 InputBuffer: ib, 250 Segments: segments, 251 } 252 253 evicted := sib.EvictSegments() 254 remaining := sib.Segments 255 So(len(evicted), ShouldEqual, 1) 256 So(len(remaining), ShouldEqual, 2) 257 So(ib.IsColdBufferDirty, ShouldBeTrue) 258 259 So(evicted[0], ShouldResembleProto, EvictedSegment{ 260 Segment: &cpb.Segment{ 261 State: cpb.SegmentState_FINALIZING, 262 HasStartChangepoint: false, 263 StartHour: timestamppb.New(time.Unix(1*3600, 0)), 264 StartPosition: 1, 265 FinalizedCounts: &cpb.Counts{ 266 TotalResults: 100, 267 UnexpectedResults: 1, 268 TotalRuns: 100, 269 UnexpectedUnretriedRuns: 1, 270 TotalVerdicts: 100, 271 UnexpectedVerdicts: 1, 272 ExpectedPassedResults: 99, 273 UnexpectedFailedResults: 1, 274 }, 275 MostRecentUnexpectedResultHour: timestamppb.New(time.Unix(51*3600, 0)), 276 }, 277 Verdicts: simpleVerdicts(100, 1, []int{50}), 278 }) 279 280 So(remaining[0], ShouldResembleProto, &Segment{ 281 StartIndex: 0, 282 EndIndex: 1949, 283 EndPosition: 2050, 284 EndHour: timestamppb.New(time.Unix(2050*3600, 0)), 285 Counts: &cpb.Counts{ 286 TotalResults: 1950, 287 UnexpectedResults: 1, 288 TotalRuns: 1950, 289 UnexpectedUnretriedRuns: 1, 290 TotalVerdicts: 1950, 291 UnexpectedVerdicts: 1, 292 ExpectedPassedResults: 1949, 293 UnexpectedFailedResults: 1, 294 }, 295 MostRecentUnexpectedResultHourAllVerdicts: timestamppb.New(time.Unix(1901*3600, 0)), 296 }) 297 298 So(remaining[1], ShouldResembleProto, &Segment{ 299 StartIndex: 1950, 300 EndIndex: 1999, 301 HasStartChangepoint: true, 302 StartPosition: 2051, 303 StartHour: timestamppb.New(time.Unix(2051*3600, 0)), 304 EndPosition: 2100, 305 EndHour: timestamppb.New(time.Unix(2100*3600, 0)), 306 Counts: &cpb.Counts{ 307 TotalResults: 50, 308 TotalRuns: 50, 309 TotalVerdicts: 50, 310 ExpectedPassedResults: 50, 311 }, 312 }) 313 }) 314 315 Convey("Evict finalized segment", t, func() { 316 ib := genInputBuffer(100, 2000, simpleVerdicts(2100, 1, []int{})) 317 segments := []*Segment{ 318 { 319 StartIndex: 0, // Finalized segment. 320 EndIndex: 39, 321 Counts: &cpb.Counts{ 322 TotalResults: 40, 323 TotalRuns: 40, 324 TotalVerdicts: 40, 325 ExpectedPassedResults: 40, 326 }, 327 HasStartChangepoint: false, 328 StartHour: timestamppb.New(time.Unix(1*3600, 0)), 329 StartPosition: 1, 330 EndHour: timestamppb.New(time.Unix(40*3600, 0)), 331 EndPosition: 40, 332 }, 333 { 334 StartIndex: 40, // Finalized segment. 335 EndIndex: 79, 336 Counts: &cpb.Counts{ 337 TotalResults: 40, 338 TotalRuns: 40, 339 TotalVerdicts: 40, 340 ExpectedPassedResults: 40, 341 }, 342 HasStartChangepoint: true, 343 StartHour: timestamppb.New(time.Unix(41*3600, 0)), 344 StartPositionLowerBound99Th: 30, 345 StartPositionUpperBound99Th: 50, 346 StartPosition: 41, 347 EndHour: timestamppb.New(time.Unix(80*3600, 0)), 348 EndPosition: 80, 349 }, 350 { 351 StartIndex: 80, // A finalizing segment. 352 EndIndex: 2049, 353 Counts: &cpb.Counts{ 354 TotalResults: 1970, 355 TotalRuns: 1970, 356 TotalVerdicts: 1970, 357 ExpectedPassedResults: 1970, 358 }, 359 HasStartChangepoint: true, 360 StartHour: timestamppb.New(time.Unix(81*3600, 0)), 361 StartPosition: 81, 362 StartPositionLowerBound99Th: 70, 363 StartPositionUpperBound99Th: 90, 364 EndHour: timestamppb.New(time.Unix(2050*3600, 0)), 365 EndPosition: 2050, 366 }, 367 { 368 StartIndex: 2050, // An active segment. 369 EndIndex: 2099, 370 Counts: &cpb.Counts{ 371 TotalResults: 50, 372 TotalRuns: 50, 373 TotalVerdicts: 50, 374 ExpectedPassedResults: 50, 375 }, 376 HasStartChangepoint: true, 377 StartHour: timestamppb.New(time.Unix(2051*3600, 0)), 378 StartPosition: 2051, 379 EndHour: timestamppb.New(time.Unix(2100*3600, 0)), 380 EndPosition: 2100, 381 }, 382 } 383 384 sib := &SegmentedInputBuffer{ 385 InputBuffer: ib, 386 Segments: segments, 387 } 388 evicted := sib.EvictSegments() 389 remaining := sib.Segments 390 So(len(evicted), ShouldEqual, 3) 391 So(len(remaining), ShouldEqual, 2) 392 So(ib.IsColdBufferDirty, ShouldBeTrue) 393 394 So(evicted[0], ShouldResembleProto, EvictedSegment{ 395 Segment: &cpb.Segment{ 396 State: cpb.SegmentState_FINALIZED, 397 HasStartChangepoint: false, 398 StartHour: timestamppb.New(time.Unix(1*3600, 0)), 399 StartPosition: 1, 400 EndHour: timestamppb.New(time.Unix(40*3600, 0)), 401 EndPosition: 40, 402 FinalizedCounts: &cpb.Counts{ 403 TotalResults: 40, 404 TotalRuns: 40, 405 TotalVerdicts: 40, 406 ExpectedPassedResults: 40, 407 }, 408 }, 409 Verdicts: simpleVerdicts(40, 1, []int{}), 410 }) 411 412 So(evicted[1], ShouldResembleProto, EvictedSegment{ 413 Segment: &cpb.Segment{ 414 State: cpb.SegmentState_FINALIZED, 415 HasStartChangepoint: true, 416 StartHour: timestamppb.New(time.Unix(41*3600, 0)), 417 StartPosition: 41, 418 StartPositionLowerBound_99Th: 30, 419 StartPositionUpperBound_99Th: 50, 420 EndHour: timestamppb.New(time.Unix(80*3600, 0)), 421 EndPosition: 80, 422 FinalizedCounts: &cpb.Counts{ 423 TotalResults: 40, 424 TotalRuns: 40, 425 TotalVerdicts: 40, 426 ExpectedPassedResults: 40, 427 }, 428 }, 429 Verdicts: simpleVerdicts(40, 41, []int{}), 430 }) 431 432 So(evicted[2], ShouldResembleProto, EvictedSegment{ 433 Segment: &cpb.Segment{ 434 State: cpb.SegmentState_FINALIZING, 435 HasStartChangepoint: true, 436 StartHour: timestamppb.New(time.Unix(81*3600, 0)), 437 StartPosition: 81, 438 StartPositionLowerBound_99Th: 70, 439 StartPositionUpperBound_99Th: 90, 440 FinalizedCounts: &cpb.Counts{ 441 TotalResults: 20, 442 TotalRuns: 20, 443 TotalVerdicts: 20, 444 ExpectedPassedResults: 20, 445 }, 446 }, 447 Verdicts: simpleVerdicts(20, 81, []int{}), 448 }) 449 450 So(remaining[0], ShouldResembleProto, &Segment{ 451 StartIndex: 0, 452 EndIndex: 1949, 453 EndPosition: 2050, 454 EndHour: timestamppb.New(time.Unix(2050*3600, 0)), 455 Counts: &cpb.Counts{ 456 TotalResults: 1950, 457 TotalRuns: 1950, 458 TotalVerdicts: 1950, 459 ExpectedPassedResults: 1950, 460 }, 461 }) 462 463 So(remaining[1], ShouldResembleProto, &Segment{ 464 StartIndex: 1950, 465 EndIndex: 1999, 466 HasStartChangepoint: true, 467 StartPosition: 2051, 468 StartHour: timestamppb.New(time.Unix(2051*3600, 0)), 469 EndPosition: 2100, 470 EndHour: timestamppb.New(time.Unix(2100*3600, 0)), 471 Counts: &cpb.Counts{ 472 TotalResults: 50, 473 TotalRuns: 50, 474 TotalVerdicts: 50, 475 ExpectedPassedResults: 50, 476 }, 477 }) 478 }) 479 480 Convey("Evict all hot buffer", t, func() { 481 ib := genInputBuffer(100, 2000, simpleVerdicts(2000, 1, []int{})) 482 ib.HotBuffer = History{ 483 Verdicts: []PositionVerdict{ 484 { 485 CommitPosition: 10, 486 }, 487 }, 488 } 489 segments := []*Segment{ 490 { 491 StartIndex: 0, // Finalized segment. 492 EndIndex: 39, 493 Counts: &cpb.Counts{ 494 TotalResults: 40, 495 TotalRuns: 40, 496 TotalVerdicts: 40, 497 ExpectedPassedResults: 40, 498 }, 499 HasStartChangepoint: false, 500 StartHour: timestamppb.New(time.Unix(1*3600, 0)), 501 StartPosition: 1, 502 EndHour: timestamppb.New(time.Unix(39*3600, 0)), 503 EndPosition: 39, 504 }, 505 { 506 StartIndex: 40, // A finalizing segment. 507 EndIndex: 2000, 508 Counts: &cpb.Counts{ 509 TotalResults: 1961, 510 TotalRuns: 1961, 511 TotalVerdicts: 1961, 512 ExpectedPassedResults: 1961, 513 }, 514 HasStartChangepoint: true, 515 StartHour: timestamppb.New(time.Unix(40*3600, 0)), 516 StartPosition: 40, 517 StartPositionLowerBound99Th: 30, 518 StartPositionUpperBound99Th: 50, 519 EndHour: timestamppb.New(time.Unix(2000*3600, 0)), 520 EndPosition: 2000, 521 }, 522 } 523 524 sib := &SegmentedInputBuffer{ 525 InputBuffer: ib, 526 Segments: segments, 527 } 528 evicted := sib.EvictSegments() 529 remaining := sib.Segments 530 So(len(evicted), ShouldEqual, 2) 531 So(len(remaining), ShouldEqual, 1) 532 So(sib.InputBuffer.IsColdBufferDirty, ShouldBeTrue) 533 534 // Hot bufffer should be empty. 535 So(len(sib.InputBuffer.HotBuffer.Verdicts), ShouldEqual, 0) 536 So(len(sib.InputBuffer.ColdBuffer.Verdicts), ShouldEqual, 1961) 537 538 expectedVerdicts := []PositionVerdict{ 539 // The verdict in the hot buffer. 540 {CommitPosition: 10}, 541 } 542 // Plus the evicted verdicts in the cold buffer. 543 expectedVerdicts = append(expectedVerdicts, simpleVerdicts(39, 1, []int{})...) 544 545 So(evicted[0], ShouldResembleProto, EvictedSegment{ 546 Segment: &cpb.Segment{ 547 State: cpb.SegmentState_FINALIZED, 548 HasStartChangepoint: false, 549 StartHour: timestamppb.New(time.Unix(1*3600, 0)), 550 StartPosition: 1, 551 EndHour: timestamppb.New(time.Unix(39*3600, 0)), 552 EndPosition: 39, 553 FinalizedCounts: &cpb.Counts{ 554 TotalResults: 40, 555 TotalRuns: 40, 556 TotalVerdicts: 40, 557 ExpectedPassedResults: 40, 558 }, 559 }, 560 Verdicts: expectedVerdicts, 561 }) 562 563 So(evicted[1], ShouldResembleProto, EvictedSegment{ 564 Segment: &cpb.Segment{ 565 State: cpb.SegmentState_FINALIZING, 566 HasStartChangepoint: true, 567 StartHour: timestamppb.New(time.Unix(40*3600, 0)), 568 StartPosition: 40, 569 StartPositionLowerBound_99Th: 30, 570 StartPositionUpperBound_99Th: 50, 571 FinalizedCounts: &cpb.Counts{}, 572 }, 573 Verdicts: []PositionVerdict{}, 574 }) 575 576 So(remaining[0], ShouldResembleProto, segments[1]) 577 }) 578 } 579 580 func simpleVerdicts(verdictCount int, startPos int, unexpectedIndices []int) []PositionVerdict { 581 positions := make([]int, verdictCount) 582 total := make([]int, verdictCount) 583 hasUnexpected := make([]int, verdictCount) 584 for i := 0; i < verdictCount; i++ { 585 positions[i] = i + startPos 586 total[i] = 1 587 } 588 for _, ui := range unexpectedIndices { 589 hasUnexpected[ui] = 1 590 } 591 return Verdicts(positions, total, hasUnexpected) 592 } 593 594 func genInputBuffer(hotCap int, coldCap int, history []PositionVerdict) *Buffer { 595 return &Buffer{ 596 HotBufferCapacity: hotCap, 597 ColdBufferCapacity: coldCap, 598 HotBuffer: History{}, 599 ColdBuffer: History{ 600 Verdicts: history, 601 }, 602 } 603 } 604 605 func genInputbufferWithRetries(hotCap int, coldCap int, positions, total, hasUnexpected, retried, unexpectedAfterRetry []int) *Buffer { 606 history := VerdictsWithRetries(positions, total, hasUnexpected, retried, unexpectedAfterRetry) 607 608 return &Buffer{ 609 HotBufferCapacity: hotCap, 610 ColdBufferCapacity: coldCap, 611 HotBuffer: History{}, 612 ColdBuffer: History{ 613 Verdicts: history, 614 }, 615 } 616 } 617 618 func BenchmarkEncode(b *testing.B) { 619 // Last known result (23-Jun-2023): 620 // cpu: Intel(R) Xeon(R) CPU @ 2.00GHz 621 // BenchmarkEncode-96 41640 31182 ns/op 2160 B/op 2 allocs/op 622 623 b.StopTimer() 624 hs := &HistorySerializer{} 625 hs.ensureAndClearBuf() 626 ib := &Buffer{ 627 HotBufferCapacity: 100, 628 HotBuffer: History{Verdicts: simpleVerdicts(100, 1, []int{5})}, 629 ColdBufferCapacity: 2000, 630 ColdBuffer: History{Verdicts: simpleVerdicts(2000, 1, []int{102, 174, 872, 971})}, 631 } 632 b.StartTimer() 633 634 for i := 0; i < b.N; i++ { 635 hs.Encode(ib.ColdBuffer) 636 hs.Encode(ib.HotBuffer) 637 } 638 } 639 640 func BenchmarkDecode(b *testing.B) { 641 // Last known result (23-Jun-2023): 642 // cpu: Intel(R) Xeon(R) CPU @ 2.00GHz 643 // BenchmarkDecode-96 20103 59558 ns/op 216 B/op 7 allocs/op 644 645 b.StopTimer() 646 var hs HistorySerializer 647 hs.ensureAndClearBuf() 648 inputBuffer := NewWithCapacity(100, 2000) 649 650 ib := &Buffer{ 651 HotBufferCapacity: 100, 652 HotBuffer: History{Verdicts: simpleVerdicts(100, 1, []int{5})}, 653 ColdBufferCapacity: 2000, 654 ColdBuffer: History{Verdicts: simpleVerdicts(2000, 1, []int{102, 174, 872, 971})}, 655 } 656 encodedColdBuffer := hs.Encode(ib.ColdBuffer) // 62 bytes compressed 657 encodedHotBuffer := hs.Encode(ib.HotBuffer) // 38 bytes compressed 658 b.StartTimer() 659 660 for i := 0; i < b.N; i++ { 661 err := hs.DecodeInto(&inputBuffer.ColdBuffer, encodedColdBuffer) 662 if err != nil { 663 panic(err) 664 } 665 err = hs.DecodeInto(&inputBuffer.HotBuffer, encodedHotBuffer) 666 if err != nil { 667 panic(err) 668 } 669 } 670 }