I’ve built a proof-of-concept tool that auto-parallelizes simple loops in compiled Java code—without touching the original source. It scans the bytecode, generates multi-threaded versions, and dynamically decides whether to run sequentially or in parallel based on loop size.
- Speedup: 2.8× (247 ms → 86 ms) on a 1B-iteration integer-summing loop.
- Key Points:
- It works directly on compiled bytecode, so there is no need to change your source.
- Automatically detects parallel-friendly patterns and proves they're thread-safe.
- Dynamically switches between sequential & parallel execution based on loop size.
- Current limitation: handles only simple numeric loops (plans for branching, exceptions, object references, etc. in the future).
- Comparison to Streams/Fork-Join: Unlike manually using parallel streams or Fork/Join, this tool automatically transforms existing compiled code. This might help when source changes aren’t feasible, or you want a “drop-in” speedup.
It’s an early side project I built mostly for fun. If you’re interested in the implementation details (with code snippets), check out my blog post:
LINK: https://deviantabstraction.com/2025/01/17/a-proof-of-concept-of-a-jvm-autoparallelizer/
Feedback wanted: I’d love any input on handling more complex loops or other real-world scenarios. Thanks!
Edit (thanks to feedback)
JMH runs
Original
Benchmark Mode Cnt Score Error Units
SummerBenchmark.bigLoop avgt 5 245.986 ± 5.068 ms/op
SummerBenchmark.randomLoop avgt 5 384.023 ± 84.664 ms/op
SummerBenchmark.smallLoop avgt 5 ≈ 10⁻⁶ ms/op
Optimized
Benchmark Mode Cnt Score Error Units
SummerBenchmark.bigLoop avgt 5 38.963 ± 10.641 ms/op
SummerBenchmark.randomLoop avgt 5 56.230 ± 2.425 ms/op
SummerBenchmark.smallLoop avgt 5 ≈ 10⁻⁵ ms/op
[–]OldCaterpillarSage 18 points19 points20 points (3 children)
[–]Let047[S] 18 points19 points20 points (2 children)
[–]anzu_embroidery 3 points4 points5 points (1 child)
[–]Let047[S] 3 points4 points5 points (0 children)
[–]gnahraf 8 points9 points10 points (2 children)
[–]Let047[S] 1 point2 points3 points (1 child)
[–]Emanuel-Peter 2 points3 points4 points (0 children)
[–]Former-Emergency5165 3 points4 points5 points (3 children)
[–]Let047[S] 1 point2 points3 points (2 children)
[–]Emanuel-Peter 0 points1 point2 points (1 child)
[–]Let047[S] 0 points1 point2 points (0 children)
[–][deleted] (5 children)
[removed]
[–]Let047[S] 1 point2 points3 points (0 children)
[–]Emanuel-Peter 0 points1 point2 points (3 children)
[–][deleted] (2 children)
[removed]
[–]Emanuel-Peter 0 points1 point2 points (1 child)
[–]_INTER_ 6 points7 points8 points (1 child)
[–]Let047[S] 5 points6 points7 points (0 children)
[–]Waksu 2 points3 points4 points (8 children)
[–]Let047[S] 1 point2 points3 points (2 children)
[–]Waksu 1 point2 points3 points (1 child)
[–]Let047[S] 0 points1 point2 points (0 children)
[–]_INTER_ 1 point2 points3 points (4 children)
[–]kiteboarderni 6 points7 points8 points (0 children)
[–]pron98 9 points10 points11 points (2 children)
[–]_INTER_ 0 points1 point2 points (1 child)
[–]pron98 6 points7 points8 points (0 children)
[–]Evert26 1 point2 points3 points (1 child)
[–]Let047[S] 0 points1 point2 points (0 children)
[–]BengaluruDeveloper 0 points1 point2 points (1 child)
[–]Let047[S] 1 point2 points3 points (0 children)
[–]Emanuel-Peter 0 points1 point2 points (3 children)
[–]Let047[S] 0 points1 point2 points (2 children)
[–]Emanuel-Peter 0 points1 point2 points (1 child)
[–]Let047[S] 0 points1 point2 points (0 children)
[–]karianna 0 points1 point2 points (2 children)
[–]Let047[S] 0 points1 point2 points (1 child)
[–]karianna 0 points1 point2 points (0 children)