github.com/dgraph-io/simdjson-go@v0.3.0/parse_json_amd64_test.go (about) 1 //+build !noasm 2 //+build !appengine 3 //+build gc 4 5 /* 6 * MinIO Cloud Storage, (C) 2020 MinIO, Inc. 7 * 8 * Licensed under the Apache License, Version 2.0 (the "License"); 9 * you may not use this file except in compliance with the License. 10 * You may obtain a copy of the License at 11 * 12 * http://www.apache.org/licenses/LICENSE-2.0 13 * 14 * Unless required by applicable law or agreed to in writing, software 15 * distributed under the License is distributed on an "AS IS" BASIS, 16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 * See the License for the specific language governing permissions and 18 * limitations under the License. 19 */ 20 21 package simdjson 22 23 import ( 24 "bytes" 25 "errors" 26 "fmt" 27 "io" 28 "math" 29 "runtime" 30 "strconv" 31 "strings" 32 "testing" 33 ) 34 35 func TestDemoNdjson(t *testing.T) { 36 37 pj := internalParsedJson{} 38 39 if err := pj.parseMessageNdjson([]byte(demo_ndjson)); err != nil { 40 t.Errorf("TestDemoNdjson: got: %v want: nil", err) 41 } 42 43 verifyDemoNdjson(pj, t, 0) 44 } 45 46 func TestNdjsonEmptyLines(t *testing.T) { 47 48 ndjson_emptylines := []string{`{"zero":"emptylines"} 49 {"c":"d"}`, 50 `{"single":"emptyline"} 51 52 {"c":"d"}`, 53 `{"dual":"emptylines"} 54 55 56 {"c":"d"}`, 57 `{"triple":"emptylines"} 58 59 60 61 {"c":"d"}`} 62 63 pj := internalParsedJson{} 64 65 for _, json := range ndjson_emptylines { 66 if err := pj.parseMessageNdjson([]byte(json)); err != nil { 67 t.Errorf("TestNdjsonEmptyLine: got: %v want: nil", err) 68 } 69 } 70 } 71 72 func BenchmarkNdjsonStage2(b *testing.B) { 73 ndjson := loadFile("testdata/parking-citations-1M.json.zst") 74 pj := internalParsedJson{} 75 76 b.SetBytes(int64(len(ndjson))) 77 b.ReportAllocs() 78 b.ResetTimer() 79 for i := 0; i < b.N; i++ { 80 err := pj.parseMessageNdjson(ndjson) 81 if err != nil { 82 panic(err) 83 } 84 } 85 } 86 87 func BenchmarkNdjsonStage1(b *testing.B) { 88 89 ndjson := loadFile("testdata/parking-citations-1M.json.zst") 90 91 pj := internalParsedJson{} 92 93 b.SetBytes(int64(len(ndjson))) 94 b.ReportAllocs() 95 b.ResetTimer() 96 97 for i := 0; i < b.N; i++ { 98 // Create new channel (large enough so we won't block) 99 pj.indexChans = make(chan indexChan, 128*10240) 100 findStructuralIndices([]byte(ndjson), &pj) 101 } 102 } 103 104 func BenchmarkNdjsonColdCountStar(b *testing.B) { 105 106 ndjson := loadFile("testdata/parking-citations-1M.json.zst") 107 108 b.SetBytes(int64(len(ndjson))) 109 b.ReportAllocs() 110 // Allocate stuff 111 pj := internalParsedJson{} 112 113 b.ResetTimer() 114 115 for i := 0; i < b.N; i++ { 116 pj.parseMessageNdjson(ndjson) 117 count_raw_tape(pj.Tape) 118 } 119 } 120 121 func BenchmarkNdjsonColdCountStarWithWhere(b *testing.B) { 122 ndjson := loadFile("testdata/parking-citations-1M.json.zst") 123 const want = 110349 124 runtime.GC() 125 pj := internalParsedJson{} 126 127 b.Run("iter", func(b *testing.B) { 128 b.SetBytes(int64(len(ndjson))) 129 b.ReportAllocs() 130 131 for i := 0; i < b.N; i++ { 132 err := pj.parseMessageNdjson(ndjson) 133 if err != nil { 134 b.Fatal(err) 135 } 136 got := countWhere("Make", "HOND", pj.ParsedJson) 137 if got != want { 138 b.Fatal(got, "!=", want) 139 } 140 } 141 }) 142 b.Run("chan", func(b *testing.B) { 143 b.SetBytes(int64(len(ndjson))) 144 b.ReportAllocs() 145 146 for i := 0; i < b.N; i++ { 147 // Temp values. 148 obj := &Object{} 149 elem := &Element{} 150 var tmp Iter 151 var nFound int 152 reuse := make(chan *ParsedJson, 1000) 153 res := make(chan Stream, 10) 154 155 ParseNDStream(bytes.NewBuffer(ndjson), res, reuse) 156 for got := range res { 157 if got.Error != nil { 158 if got.Error == io.EOF { 159 break 160 } 161 b.Fatal(got.Error) 162 } 163 164 all := got.Value.Iter() 165 // NDJSON is a separated by root objects. 166 for all.Advance() == TypeRoot { 167 // Read inside root. 168 t, i, err := all.Root(&tmp) 169 if t != TypeObject { 170 b.Log("got type", t.String()) 171 continue 172 } 173 174 // Prepare object. 175 obj, err = i.Object(obj) 176 if err != nil { 177 b.Log("got err", err) 178 continue 179 } 180 181 // Find Make key. 182 elem = obj.FindKey("Make", elem) 183 if elem.Type != TypeString { 184 b.Log("got type", err) 185 continue 186 } 187 asB, err := elem.Iter.StringBytes() 188 if err != nil { 189 b.Log("got err", err) 190 continue 191 } 192 if bytes.Equal(asB, []byte("HOND")) { 193 nFound++ 194 } 195 } 196 reuse <- got.Value 197 } 198 if nFound != want { 199 b.Fatal(nFound, "!=", want) 200 } 201 } 202 }) 203 204 } 205 206 func TestParseNumber(t *testing.T) { 207 testCases := []struct { 208 input string 209 wantTag Tag 210 expectedD float64 211 expectedI int64 212 expectedU uint64 213 flags FloatFlags 214 }{ 215 {input: "1", wantTag: TagInteger, expectedI: 1}, 216 {input: "-1", wantTag: TagInteger, expectedI: -1}, 217 {input: "10000000000000000000", wantTag: TagUint, expectedU: 10000000000000000000}, 218 {input: "10000000000000000001", wantTag: TagUint, expectedU: 10000000000000000001}, 219 // math.MinInt64 - 1 220 {input: "-9223372036854775809", wantTag: TagFloat, expectedD: -9.223372036854776e+18, flags: FloatOverflowedInteger.Flags()}, 221 {input: "-10000000000000000000", wantTag: TagFloat, expectedD: -10000000000000000000, flags: FloatOverflowedInteger.Flags()}, 222 {input: "100000000000000000000", wantTag: TagFloat, expectedD: 100000000000000000000, flags: FloatOverflowedInteger.Flags()}, 223 // math.MaxUint64 +1 224 {input: "18446744073709551616", wantTag: TagFloat, expectedD: 1.8446744073709552e+19, flags: FloatOverflowedInteger.Flags()}, 225 {input: "1.0", wantTag: TagFloat, expectedD: 1.0}, 226 {input: "1234567890", wantTag: TagInteger, expectedI: 1234567890}, 227 {input: "9876.543210", wantTag: TagFloat, expectedD: 9876.543210}, 228 {input: "0.123456789e-12", wantTag: TagFloat, expectedD: 1.23456789e-13}, 229 {input: "1.234567890E+34", wantTag: TagFloat, expectedD: 1.234567890e+34}, 230 {input: "23456789012E66", wantTag: TagFloat, expectedD: 23456789012e66}, 231 {input: "-9876.543210", wantTag: TagFloat, expectedD: -9876.543210}, 232 {input: "-65.619720000000029", wantTag: TagFloat, expectedD: -65.61972000000003}, 233 } 234 235 for _, tc := range testCases { 236 tag, val, flags, _ := parseNumber([]byte(fmt.Sprintf(`%s:`, tc.input))) 237 if tag != tc.wantTag { 238 t.Errorf("TestParseNumber: got: %v want: %v", tag, tc.wantTag) 239 } 240 switch tag { 241 case TagFloat: 242 got := math.Float64frombits(val) 243 if !closeEnough(got, tc.expectedD) { 244 t.Errorf("TestParseNumber: got: %g want: %g", got, tc.expectedD) 245 } 246 case TagInteger: 247 if tc.expectedI != int64(val) { 248 t.Errorf("TestParseNumber: got: %d want: %d", int64(val), tc.expectedI) 249 } 250 case TagUint: 251 if tc.expectedU != val { 252 t.Errorf("TestParseNumber: got: %d want: %d", val, tc.expectedU) 253 } 254 } 255 if flags != uint64(tc.flags) { 256 t.Errorf("TestParseNumber flags; got: %d want: %d", flags, tc.flags) 257 } 258 } 259 } 260 261 // The following code is borrowed from Golang (https://golang.org/src/strconv/atoi_test.go) 262 263 type parseInt64Test struct { 264 in string 265 out int64 266 tag Tag 267 } 268 269 var parseInt64Tests = []parseInt64Test{ 270 {"", 0, TagEnd}, 271 {"0", 0, TagInteger}, 272 {"-0", 0, TagInteger}, 273 {"1", 1, TagInteger}, 274 {"-1", -1, TagInteger}, 275 {"12345", 12345, TagInteger}, 276 {"-12345", -12345, TagInteger}, 277 {"012345", 0, TagEnd}, 278 {"-012345", 0, TagEnd}, 279 {"98765432100", 98765432100, TagInteger}, 280 {"-98765432100", -98765432100, TagInteger}, 281 {"9223372036854775807", 1<<63 - 1, TagInteger}, 282 {"-9223372036854775807", -(1<<63 - 1), TagInteger}, 283 {"9223372036854775808", 1<<63 - 1, TagUint}, 284 {"-9223372036854775808", -1 << 63, TagInteger}, 285 {"9223372036854775809", 1<<63 - 1, TagUint}, 286 {"-9223372036854775809", -1 << 63, TagFloat}, 287 {"-1_2_3_4_5", 0, TagEnd}, // base=10 so no underscores allowed 288 {"-_12345", 0, TagEnd}, 289 {"_12345", 0, TagEnd}, 290 {"1__2345", 0, TagEnd}, 291 {"12345_", 0, TagEnd}, 292 293 // zero (originate from atof tests below, but returned as int for simdjson) 294 {"0e0", 0, TagFloat}, 295 {"-0e0", 0, TagFloat}, 296 {"0e-0", 0, TagFloat}, 297 {"-0e-0", 0, TagFloat}, 298 {"0e+0", 0, TagFloat}, 299 {"-0e+0", 0, TagFloat}, 300 } 301 302 func TestParseInt64(t *testing.T) { 303 for i := range parseInt64Tests { 304 test := &parseInt64Tests[i] 305 t.Run(test.in, func(t *testing.T) { 306 307 tag, val, _, _ := parseNumber([]byte(fmt.Sprintf(`%s:`, test.in))) 308 if tag != test.tag { 309 // Ignore intentionally bad syntactical errors 310 t.Errorf("TestParseInt64: got: %v want: %v", tag, test.tag) 311 return // skip testing the rest for this test case 312 } 313 if tag == TagInteger && int64(val) != test.out { 314 // Ignore intentionally wrong conversions 315 t.Errorf("TestParseInt64: got value: %v want: %v", int64(val), test.out) 316 } 317 }) 318 319 } 320 } 321 322 // The following code is borrowed from Golang (https://golang.org/src/strconv/atof_test.go) 323 324 type atofTest struct { 325 in string 326 out string 327 err error 328 } 329 330 var atoftests = []atofTest{ 331 {"", "0", strconv.ErrSyntax}, /* fails for simdjson */ 332 {"1", "1", nil}, /* parsed as int for simdjson */ 333 {"+1", "1", nil}, /* parsed as int for simdjson */ 334 335 {"1x", "0", strconv.ErrSyntax}, 336 {"1.1.", "0", strconv.ErrSyntax}, 337 {"1e23", "1e+23", nil}, 338 {"1E23", "1e+23", nil}, 339 {"100000000000000000000000", "1e+23", nil}, /* parsed as int for simdjson */ 340 {"1e-100", "1e-100", nil}, 341 {"123456700", "123456700", nil}, /* parsed as int for simdjson */ 342 {"99999999999999974834176", "9.999999999999997e+22", nil}, /* parsed as int for simdjson */ 343 {"100000000000000000000001", "1.0000000000000001e+23", nil}, /* parsed as int for simdjson */ 344 {"100000000000000008388608", "1.0000000000000001e+23", nil}, /* parsed as int for simdjson */ 345 {"100000000000000016777215", "1.0000000000000001e+23", nil}, /* parsed as int for simdjson */ 346 {"100000000000000016777216", "1.0000000000000003e+23", nil}, /* parsed as int for simdjson */ 347 {"-1", "-1", nil}, /* parsed as int for simdjson */ 348 {"-0.1", "-0.1", nil}, 349 {"-0", "0", nil}, /* parsed as int for simdjson */ 350 {"1e-20", "1e-20", nil}, 351 {"625e-3", "0.625", nil}, 352 353 // zeros (several test cases for zero have been moved up because they are detected as ints) 354 {"+0e0", "0", nil}, 355 {"+0e-0", "0", nil}, 356 {"+0e+0", "0", nil}, 357 {"0e+01234567890123456789", "0", nil}, 358 {"0.00e-01234567890123456789", "0", nil}, 359 {"-0e+01234567890123456789", "-0", nil}, 360 {"-0.00e-01234567890123456789", "-0", nil}, 361 362 {"0e291", "0", nil}, // issue 15364 363 {"0e292", "0", nil}, // issue 15364 364 {"0e347", "0", nil}, // issue 15364 365 {"0e348", "0", nil}, // issue 15364 366 {"-0e291", "-0", nil}, /* returns "0" */ 367 {"-0e292", "-0", nil}, /* returns "0" */ 368 {"-0e347", "-0", nil}, /* returns "0" */ 369 {"-0e348", "-0", nil}, /* returns "0" */ 370 371 // NaNs 372 {"nan", "NaN", errors.New("invalid json")}, 373 {"NaN", "NaN", errors.New("invalid json")}, 374 {"NAN", "NaN", errors.New("invalid json")}, 375 376 // Infs 377 {"inf", "+Inf", errors.New("invalid json")}, 378 {"-Inf", "-Inf", errors.New("invalid json")}, 379 {"+INF", "+Inf", errors.New("invalid json")}, 380 {"-Infinity", "-Inf", errors.New("invalid json")}, 381 {"+INFINITY", "+Inf", errors.New("invalid json")}, 382 {"Infinity", "+Inf", errors.New("invalid json")}, 383 384 // largest float64 385 {"1.7976931348623157e308", "1.7976931348623157e+308", nil}, 386 {"-1.7976931348623157e308", "-1.7976931348623157e+308", nil}, 387 388 // next float64 - too large 389 {"1.7976931348623159e308", "+Inf", strconv.ErrRange}, 390 {"-1.7976931348623159e308", "-Inf", strconv.ErrRange}, 391 392 {"1.7976931348623158e308", "1.7976931348623157e+308", nil}, 393 {"-1.7976931348623158e308", "-1.7976931348623157e+308", nil}, 394 395 // borderline - too large 396 {"1.797693134862315808e308", "+Inf", strconv.ErrRange}, 397 {"-1.797693134862315808e308", "-Inf", strconv.ErrRange}, 398 399 // a little too large 400 {"1e308", "1e+308", nil}, 401 {"2e308", "+Inf", strconv.ErrRange}, 402 {"1e309", "+Inf", strconv.ErrRange}, 403 404 // way too large 405 {"1e310", "+Inf", strconv.ErrRange}, 406 {"-1e310", "-Inf", strconv.ErrRange}, 407 {"1e400", "+Inf", strconv.ErrRange}, 408 {"-1e400", "-Inf", strconv.ErrRange}, 409 {"1e400000", "+Inf", strconv.ErrRange}, 410 {"-1e400000", "-Inf", strconv.ErrRange}, 411 412 // denormalized 413 {"1e-305", "1e-305", nil}, 414 {"1e-306", "1e-306", nil}, 415 {"1e-307", "1e-307", nil}, 416 {"1e-308", "1e-308", nil}, 417 {"1e-309", "1e-309", nil}, 418 {"1e-310", "1e-310", nil}, 419 {"1e-322", "1e-322", nil}, 420 // smallest denormal 421 {"5e-324", "5e-324", nil}, 422 {"4e-324", "5e-324", nil}, 423 {"3e-324", "5e-324", nil}, 424 // too small 425 {"2e-324", "0", nil}, 426 // way too small 427 {"1e-350", "0", nil}, 428 {"1e-400000", "0", nil}, 429 430 // try to overflow exponent 431 {"1e-4294967296", "0", nil}, 432 {"1e+4294967296", "+Inf", strconv.ErrRange}, 433 {"1e-18446744073709551616", "0", nil}, 434 {"1e+18446744073709551616", "+Inf", strconv.ErrRange}, 435 436 // Parse errors 437 {"1e", "0", strconv.ErrSyntax}, 438 {"1e-", "0", strconv.ErrSyntax}, 439 {".e-1", "0", strconv.ErrSyntax}, 440 441 // https://www.exploringbinary.com/java-hangs-when-converting-2-2250738585072012e-308/ 442 {"2.2250738585072012e-308", "2.2250738585072014e-308", nil}, 443 // https://www.exploringbinary.com/php-hangs-on-numeric-value-2-2250738585072011e-308/ 444 {"2.2250738585072011e-308", "2.225073858507201e-308", nil}, 445 446 // A very large number (initially wrongly parsed by the fast algorithm). 447 {"4.630813248087435e+307", "4.630813248087435e+307", nil}, 448 449 // A different kind of very large number. 450 {"22.222222222222222", "22.22222222222222", nil}, 451 {"2." + strings.Repeat("2", 4000) + "e+1", "22.22222222222222", nil}, 452 453 // Exactly halfway between 1 and math.Nextafter(1, 2). 454 // Round to even (down). 455 {"1.00000000000000011102230246251565404236316680908203125", "1", nil}, 456 // Slightly lower; still round down. 457 {"1.00000000000000011102230246251565404236316680908203124", "1", nil}, 458 // Slightly higher; round up. 459 {"1.00000000000000011102230246251565404236316680908203126", "1.0000000000000002", nil}, 460 // Slightly higher, but you have to read all the way to the end. 461 {"1.00000000000000011102230246251565404236316680908203125" + strings.Repeat("0", 10000) + "1", "1.0000000000000002", nil}, 462 463 // Halfway between x := math.Nextafter(1, 2) and math.Nextafter(x, 2) 464 // Round to even (up). 465 {"1.00000000000000033306690738754696212708950042724609375", "1.0000000000000004", nil}, 466 467 // Underscores. 468 {"1_23.50_0_0e+1_2", "1.235e+14", strconv.ErrSyntax}, 469 {"-_123.5e+12", "0", strconv.ErrSyntax}, 470 {"+_123.5e+12", "0", strconv.ErrSyntax}, 471 {"_123.5e+12", "0", strconv.ErrSyntax}, 472 {"1__23.5e+12", "0", strconv.ErrSyntax}, 473 {"123_.5e+12", "0", strconv.ErrSyntax}, 474 {"123._5e+12", "0", strconv.ErrSyntax}, 475 {"123.5_e+12", "0", strconv.ErrSyntax}, 476 {"123.5__0e+12", "0", strconv.ErrSyntax}, 477 {"123.5e_+12", "0", strconv.ErrSyntax}, 478 {"123.5e+_12", "0", strconv.ErrSyntax}, 479 {"123.5e_-12", "0", strconv.ErrSyntax}, 480 {"123.5e-_12", "0", strconv.ErrSyntax}, 481 {"123.5e+1__2", "0", strconv.ErrSyntax}, 482 {"123.5e+12_", "0", strconv.ErrSyntax}, 483 } 484 485 func TestParseFloat64(t *testing.T) { 486 487 for i := 0; i < len(atoftests); i++ { 488 test := &atoftests[i] 489 t.Run(test.in, func(t *testing.T) { 490 tag, val, _, _ := parseNumber([]byte(fmt.Sprintf(`%s:`, test.in))) 491 switch tag { 492 case TagEnd: 493 if test.err == nil { 494 t.Errorf("TestParseFloat64: got error, none") 495 } 496 case TagFloat: 497 got := math.Float64frombits(val) 498 outs := strconv.FormatFloat(got, 'g', -1, 64) 499 if outs != test.out { 500 t.Errorf("TestParseFloat64: got: %v want: %v", outs, test.out) 501 } 502 case TagInteger: 503 got := int64(val) 504 outs := fmt.Sprint(got) 505 if outs != test.out { 506 t.Errorf("TestParseFloat64: got: %v want: %v", outs, test.out) 507 } 508 case TagUint: 509 got := val 510 outs := fmt.Sprint(got) 511 if outs != test.out { 512 t.Errorf("TestParseFloat64: got: %v want: %v", outs, test.out) 513 } 514 default: 515 } 516 }) 517 } 518 } 519 520 func TestParseString(t *testing.T) { 521 522 for _, tt := range tests { 523 t.Run(tt.name, func(t *testing.T) { 524 // enclose test string in quotes (as validated by stage 1) 525 buf := []byte(fmt.Sprintf(`"%s"`, tt.str)) 526 dest := make([]byte, 0, len(buf)+32 /* safety margin as parseString writes full AVX2 words */) 527 528 success := parseStringSimd(buf, &dest) 529 530 if success != tt.success { 531 t.Errorf("TestParseString() got = %v, want %v", success, tt.success) 532 } 533 if success { 534 size := len(dest) 535 if size != len(tt.want) { 536 t.Errorf("TestParseString() got = %d, want %d", size, len(tt.want)) 537 } 538 if bytes.Compare(dest[:size], tt.want) != 0 { 539 t.Errorf("TestParseString() got = %v, want %v", dest[:size], tt.want) 540 } 541 } 542 }) 543 } 544 } 545 546 func TestParseStringValidateOnly(t *testing.T) { 547 548 for _, tt := range tests { 549 t.Run(tt.name, func(t *testing.T) { 550 // enclose test string in quotes (as validated by stage 1) 551 buf := []byte(fmt.Sprintf(`"%s"`, tt.str)) 552 553 dst_length := uint64(0) 554 need_copy := false 555 l := uint64(len(buf)) 556 success := parseStringSimdValidateOnly(buf, &l, &dst_length, &need_copy) 557 558 if success != tt.success { 559 t.Errorf("TestParseString() got = %v, want %v", success, tt.success) 560 } 561 if success && !need_copy { 562 if dst_length != uint64(len(tt.want)) { 563 t.Errorf("TestParseString() got = %d, want %d", dst_length, len(tt.want)) 564 } 565 } 566 }) 567 } 568 } 569 570 func TestParseStringValidateOnlyBeyondBuffer(t *testing.T) { 571 572 t.Skip() 573 574 buf := []byte(fmt.Sprintf(`"%s`, " ")) 575 576 dst_length := uint64(0) 577 need_copy := false 578 l := uint64(len(buf)) + 32 579 success := parseStringSimdValidateOnly(buf, &l, &dst_length, &need_copy) 580 if !success { 581 t.Errorf("TestParseStringValidateOnlyBeyondBuffer() got = %v, want %v", success, false) 582 } 583 } 584 585 // Benchmarking code for integers 586 587 func BenchmarkParseNumber(b *testing.B) { 588 b.Run("Pos", func(b *testing.B) { 589 benchmarkParseNumber(b, 1) 590 }) 591 b.Run("Neg", func(b *testing.B) { 592 benchmarkParseNumber(b, -1) 593 }) 594 } 595 596 func benchmarkParseNumber(b *testing.B, neg int) { 597 cases := []benchCase{ 598 {"63bit", 1<<63 - 1}, 599 } 600 for _, cs := range cases { 601 b.Run(cs.name, func(b *testing.B) { 602 s := fmt.Sprintf("%d", cs.num*int64(neg)) 603 s = fmt.Sprintf(`%s:`, s) // append delimiter 604 for i := 0; i < b.N; i++ { 605 parseNumber([]byte(s)) 606 } 607 }) 608 } 609 } 610 611 func BenchmarkParseNumberFloat(b *testing.B) { 612 for i := 0; i < b.N; i++ { 613 parseNumber([]byte("339.7784:")) 614 } 615 } 616 617 func BenchmarkParseAtof64FloatGolang(b *testing.B) { 618 for i := 0; i < b.N; i++ { 619 strconv.ParseFloat("339.7784", 64) 620 } 621 } 622 623 func BenchmarkParseNumberFloatExp(b *testing.B) { 624 for i := 0; i < b.N; i++ { 625 parseNumber([]byte("-5.09e75:")) 626 } 627 } 628 629 func BenchmarkParseNumberBig(b *testing.B) { 630 for i := 0; i < b.N; i++ { 631 parseNumber([]byte("123456789123456789123456789:")) 632 } 633 } 634 635 func BenchmarkParseNumberRandomBits(b *testing.B) { 636 initAtof() 637 for i := 0; i < b.N; i++ { 638 parseNumber([]byte(benchmarksRandomBitsSimd[i%1024])) 639 } 640 } 641 642 func BenchmarkParseNumberRandomFloats(b *testing.B) { 643 initAtof() 644 for i := 0; i < b.N; i++ { 645 parseNumber([]byte(benchmarksRandomNormalSimd[i%1024])) 646 } 647 } 648 649 func TestVerifyTape(t *testing.T) { 650 // FIXME: Does not have tapes any more. 651 for _, tt := range testCases { 652 653 t.Run(tt.name, func(t *testing.T) { 654 ref := loadCompressed(t, tt.name) 655 656 pj := internalParsedJson{} 657 if err := pj.parseMessage(ref); err != nil { 658 t.Errorf("parseMessage failed: %v\n", err) 659 return 660 } 661 662 //ctape := bytesToUint64(cbuf) 663 664 //testCTapeCtoGoTapeCompare(t, ctape, csbuf, pj) 665 }) 666 } 667 }