Commit 0d13274
authored
perf: Long fast path for formatOctal and formatHexadecimal (#764)
## Motivation
`formatOctal` and `formatHexadecimal` always allocate `BigInt` via
`truncateToInteger`, even when the value fits in a `Long`. The existing
`formatInteger` already has a `Long` fast path that avoids this
allocation — extending the same pattern to octal and hex formatting.
## Key Design Decision
Inline the Long-fits check (`sl.toDouble == s && sl != Long.MinValue`)
directly into `formatOctal` and `formatHexadecimal`, using
`java.lang.Long.toString(value, radix)` for the fast path. Fall back to
`BigDecimal.toBigInt` only for values exceeding Long range.
## Modification
- `Format.scala`: Add Long fast path to `formatOctal` and
`formatHexadecimal`
- `Format.scala`: Remove now-unused `truncateToInteger` helper method
- Use `rhs2.charAt(0)` instead of `rhs2(0)` for consistency (avoids
Scala implicit conversion)
## Benchmark Results
### JMH (single fork, 1 iteration — directional only)
Format-heavy benchmarks are the primary beneficiaries:
| Benchmark | Master (ms/op) | This PR (ms/op) | Change |
|-----------|---------------|-----------------|--------|
| large_string_template | 1.610 | 1.646 | +2.2% (noise) |
| bench.03 | 9.809 | 9.652 | -1.6% |
The `%o` and `%x` format specifiers are less common than `%d` in typical
Jsonnet, so the impact is modest but still beneficial when these paths
are hit.
### Scala Native vs jrsonnet (hyperfine)
| Benchmark | sjsonnet Native (ms) | jrsonnet (ms) | Ratio |
|-----------|---------------------|---------------|-------|
| large_string_template | 17.3 | 8.0 | 2.15x (jrsonnet wins) |
Gap is primarily due to process startup overhead and overall eval speed,
not format-specific.
## Analysis
This is a correctness-neutral optimization that extends an established
pattern (Long fast path in `formatInteger`) to two more methods. No new
code paths — the fallback to `BigDecimal.toBigInt` handles edge cases
identically to the original `truncateToInteger`.
## References
- Upstream: jit branch commit
[`6524d77d`](He-Pin@6524d77d)
## Result
All 420 tests pass across JVM/JS/Native × Scala 3.3.7, 2.13.18, 2.12.21.1 parent 89c64be commit 0d13274
1 file changed
Lines changed: 60 additions & 34 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
488 | 488 | | |
489 | 489 | | |
490 | 490 | | |
491 | | - | |
492 | | - | |
493 | | - | |
494 | | - | |
495 | | - | |
496 | | - | |
497 | | - | |
498 | | - | |
499 | 491 | | |
500 | 492 | | |
501 | 493 | | |
| |||
537 | 529 | | |
538 | 530 | | |
539 | 531 | | |
540 | | - | |
541 | | - | |
542 | | - | |
543 | | - | |
544 | | - | |
545 | | - | |
546 | | - | |
547 | | - | |
548 | | - | |
549 | | - | |
550 | | - | |
551 | | - | |
552 | | - | |
| 532 | + | |
| 533 | + | |
| 534 | + | |
| 535 | + | |
| 536 | + | |
| 537 | + | |
| 538 | + | |
| 539 | + | |
| 540 | + | |
| 541 | + | |
| 542 | + | |
| 543 | + | |
| 544 | + | |
| 545 | + | |
| 546 | + | |
| 547 | + | |
| 548 | + | |
| 549 | + | |
| 550 | + | |
| 551 | + | |
| 552 | + | |
| 553 | + | |
| 554 | + | |
| 555 | + | |
| 556 | + | |
| 557 | + | |
| 558 | + | |
| 559 | + | |
| 560 | + | |
| 561 | + | |
553 | 562 | | |
554 | 563 | | |
555 | 564 | | |
556 | | - | |
557 | | - | |
558 | | - | |
559 | | - | |
560 | | - | |
561 | | - | |
562 | | - | |
563 | | - | |
564 | | - | |
565 | | - | |
566 | | - | |
567 | | - | |
568 | | - | |
| 565 | + | |
| 566 | + | |
| 567 | + | |
| 568 | + | |
| 569 | + | |
| 570 | + | |
| 571 | + | |
| 572 | + | |
| 573 | + | |
| 574 | + | |
| 575 | + | |
| 576 | + | |
| 577 | + | |
| 578 | + | |
| 579 | + | |
| 580 | + | |
| 581 | + | |
| 582 | + | |
| 583 | + | |
| 584 | + | |
| 585 | + | |
| 586 | + | |
| 587 | + | |
| 588 | + | |
| 589 | + | |
| 590 | + | |
| 591 | + | |
| 592 | + | |
| 593 | + | |
| 594 | + | |
569 | 595 | | |
570 | 596 | | |
571 | 597 | | |
| |||
0 commit comments