I Built a Stable Sorting Algorithm That Beats Java's Dual-Pivot Quicksort
Source: Dev.to
A few days ago I finished benchmarking something I’ve been building - a cache-aware, stable, histogram-based sorting algorithm I’m calling BusSort. The results surprised even me. At 100 million elements, it runs ~2x faster than Java’s Dual-Pivot Quicksort on random data - while being stable. Dual-Pivot QS is not. Quicksort-based algorithms partition elements with random writes across the entire array. At large scales this causes cache thrashing - elements are being written to memory locations all over the place, constantly missing L1 and L2 cache. The larger the array, the worse it gets. Instead of scattering elements globally, BusSort processes data in L1 cache-sized chunks - 4096 integers (~16KB). For each chunk, it does 4 passes: PASS 1 - Scan left-to-right, compute bucket for each element, build a local histogram PASS 2 - Compute local prefix sums (bucket positions within the chunk) PASS 3 - Scatter into a local grouped buffer - because this buffer is L1-sized, all random writes stay in cache ✅ PASS 4 - Copy each bucket’s portion to its correct global position With 128-way splitting, recursion depth stays at just ~4 levels even for 100M elements. Base case: Insertion Sort for ≤ 1024 elements. On the benchmark machine (i5-1135G7, 48KB L1 data cache): 4096 × 3 × 4 bytes = 49,152 bytes ≈ 48KB
The three working arrays fit exactly in L1. Not a coincidence. Tested against Arrays.sort(int[]) - Java’s Dual-Pivot Quicksort. n = 100,000,000 | Java 17 | i5-1135G7 @ 2.40GHz
Input Type BusSort Dual-Pivot QS Ratio
Random 3991ms 8604ms ~2x
Sorted 57ms 104ms ~2x
Reverse 280ms 166ms 0.6x
Nearly Sorted 2452ms 2789ms ~1.1x
Duplicates 712ms 2242ms ~2.4x
Few Duplicates 1295ms 3185ms ~2.3x
All Same 51ms 32ms 0.6x
Clustered 1419ms 2242ms ~1.6x
Consistently faster on most input types. Stable. Zero comparison overhead. The two losses (Reverse, All Same) are where Dual-Pivot QS has structural advantages - run detection and early termination. BusSort preserves relative order of equal elements because: Chunks are processed left-to-right
Within each chunk, elements are scattered left-to-right
globalNext[b] advances per chunk - earlier chunks always land before later chunks This makes BusSort one of very few algorithms that is both faster than Dual-Pivot Quicksort and stable. Requires O(n) auxiliary space - standard for stable sorts Slower than Dual-Pivot Quicksort on already-sorted and reverse-sorted input Currently supports int[] only - generic support coming soon Generic object support with Comparator
Benchmark against TimSort on Integer[]
Parallel variant JMH benchmarks for more rigorous measurement This is a work in progress. Theory, benchmarks, and current implementation are published. 👉 github.com/dev-shreyaspatil/BusSort Curious what the Java community thinks - especially around the cache-chunking approach and whether there are similar published algorithms I should be comparing against.