Radix Plus
A high performance, in place Radix Sort library for Dart and Flutter.
Fast. Efficient. Low level sorting for number intensive applications.
About • Features • Tech Stack • Prerequisites • Installation • Quick Start • Usage • Benchmarks • Architecture • Parameters • Scripts • Testing • Deployment • Troubleshooting • Contributing • License
About
Welcome to Radix Plus a blazing fast, in place sorting library for Dart and Flutter.
Radix Plus provides a set of highly optimized, stable sorting algorithms that can be significantly faster than List.sort() for specific data types, especially large lists of numbers (int, double, and BigInt). It uses low-level byte manipulation to achieve top-tier performance, making it ideal for data-intensive applications, scientific computing, and real time data processing.
Features
🌟 Core Functionality
- Multi-Type Support: Sorts
List<int>,List<double>, andList<BigInt>. - Stable Sort: Preserves the relative order of equal elements.
- Unified Integer API: A single function,
radixSortInt, handles both signed and unsigned integers. - Comprehensive Float Support:
radixSortDoublecorrectly handles positive/negative values, infinities, and zero.
🛠️ Advanced Capabilities
- Parallel Sorting:
radixSortParallelUnsignedandradixSortParallelSignedleverage multiple CPU cores using Isolates to sort very large lists even faster. - Memory Efficiency: Includes a buffer pooling mechanism (
reuseBuffer: true) to minimize GC pressure during frequent sorting tasks. - Zero-Copy Operations: Works directly on
TypedDatalists (Int32List,Float64List, etc.) to avoid unnecessary memory copies. - Adaptive Algorithms: Uses hybrid strategies (like switching to insertion sort for small sub-lists under 32 elements) for optimal performance across different data sizes.
Tech Stack
- Language: Dart 3.0.0+ / Flutter compatible
- Core Library:
dart:typed_datafor low-level memory reinterpretation views - Concurrency:
dart:isolatefor multi-threaded parallel sorting - Testing:
package:test - Benchmarking:
package:benchmark_harness - Dependencies:
package:collectionfor list utilities,package:lintsfor code health
Prerequisites
- Dart SDK:
>=3.0.0 <4.0.0 - Flutter SDK (Optional): For integration with mobile, desktop, or web UI apps
Installation
📦 Add to your project
-
Add this to your package's
pubspec.yamlfile:dependencies: radix_plus: ^1.0.6 -
Install it from your terminal:
dart pub getor
flutter pub get
🚀 Quick Start
Import the library and call the appropriate sorting function.
import 'package:radix_plus/radix_plus.dart';
void main() {
// Sort a list of signed integers
final numbers = [40, -1, 900, -10, 0, 5];
radixSortInt(numbers); // Automatically handles signed integers
print(numbers); // [-10, -1, 0, 5, 40, 900]
}
📋 Usage Examples
Sorting Integers
Use radixSortInt for both signed and unsigned integer lists.
// Sort a list of signed integers (ascending)
final signedNumbers = [40, -1, 900, -10, 0, 5];
radixSortInt(signedNumbers, ascending: true);
print(signedNumbers); // [-10, -1, 0, 5, 40, 900]
// Sort a list of unsigned integers (descending)
final unsignedNumbers = [40, 1, 900, 10, 5];
radixSortInt(unsignedNumbers, signed: false, ascending: false);
print(unsignedNumbers); // [900, 40, 10, 5, 1]
Sorting Doubles
Use radixSortDouble for List<double>.
final doubleNumbers = [10.5, -1.2, 900.0, -10.0, 0.0];
radixSortDouble(doubleNumbers);
print(doubleNumbers); // [-10.0, -1.2, 0.0, 10.5, 900.0]
Sorting BigInts
Use radixSortBigInt for List<BigInt>.
final bigIntNumbers = [
BigInt.parse('100000000000000000000'),
BigInt.from(-100),
BigInt.parse('-200000000000000000000'),
BigInt.zero,
];
radixSortBigInt(bigIntNumbers);
print(bigIntNumbers);
Parallel Sorting
For very large lists, radixSortParallelUnsigned can provide a significant speed boost.
Note: Parallel sorting is not available on the Web platform.
// A large list of numbers
final largeList = List.generate(1000000, (i) => 999999 - i);
// Sort it in parallel across multiple isolates
await radixSortParallelUnsigned(largeList);
print(largeList.first); // 0
print(largeList.last); // 999999
🚀 Benchmarks
Performance is the core feature of Radix Plus. Our algorithms are consistently faster than the standard List.sort() for large numerical datasets, often by a significant margin.
To ensure accuracy, the results below are the average of 10 separate benchmark runs on a standard development machine AMD Ryzen™ 7 5800H, each sorting a list of 1,000,000 random elements.
🔹 Integers (List<int>)
| Method | Average Time (ms) | Speedup vs. List.sort() |
|---|---|---|
List.sort() |
~1785 | 1.0x |
radixSortInt |
~282 | ~6.3x faster |
🔹 Typed Lists (32-bit Integers)
Typed lists (Int32List, Uint32List) achieve even better performance due to optimized memory layout.
🔸 Int32List
| Method | Average Time (ms) | Speedup vs. List.sort() |
|---|---|---|
List.sort() |
~1490 | 1.0x |
radixSortInt32 |
~201 | ~7.4x faster |
🔸 Uint32List
| Method | Average Time (ms) | Speedup vs. List.sort() |
|---|---|---|
List.sort() |
~1477 | 1.0x |
radixSortUint32 |
~183 | ~8.1x faster |
🔹 Floating Point Numbers
Supports both List<double> and optimized Float64List, including correct handling of NaN values.
🔸 List<double>
| Method | Average Time (ms) | Speedup vs. List.sort() |
|---|---|---|
List.sort() |
~2634 | 1.0x |
radixSortDouble |
~578 | ~4.6x faster |
🔸 Float64List
| Method | Average Time (ms) | Speedup vs. List.sort() |
|---|---|---|
List.sort() |
~1444 | 1.0x |
radixSortFloat64 |
~394 | ~3.7x faster |
radixSortFloat64WithNaN |
~312 | ~4.6x faster |
🔹 BigInt
Efficient sorting for arbitrary-precision integers.
| Method | Average Time (ms) | Speedup vs. List.sort() |
|---|---|---|
List.sort() |
~6667 | 1.0x |
radixSortBigInt |
~1074 | ~6.2x faster |
radixSortBigIntWithRange |
~6869 | ~0.97x faster |
ℹ️
radixSortBigIntWithRangeis optimized for specific range-based scenarios, not general-purpose sorting.
⚡ Parallel Sorting (Multi-threaded)
Leverages Dart Isolates to unlock massive speedups on multi-core CPUs.
| Method | Average Time (ms) | Speedup vs. List.sort() |
|---|---|---|
List.sort() (Standard int) |
~1612 | 1.0x |
radixSortParallelUnsigned |
~26.6 | ~60.7x faster |
radixSortParallelSigned |
~28.8 | ~56.1x faster |
Data Sort Lifecycle & Flows
[Input Double List] ──► Map bits to Unsigned (Positive XOR sign bit, Negative bitwise-negate)
│
▼
[Memory View] ──► Reinterpret Float64List buffer as Uint64List (zero-copy)
│
▼
[Core 64-bit Radix] ──► Run 8 passes, 8-bits per pass. Skips pass if minBucket == maxBucket.
│
▼
[Revert Mapping] ──► Transform bitwise values back to native Double list
│
▼
[Sorted Output]
Concurrency Model (K-Way Min-Heap Merge)
When parallel sorting is triggered:
- The list is sliced into balanced segments matching thread requirements.
- Isolates are spawned in parallel to sort each sub-slice sequentially.
- The main thread performs a zero-allocation k-Way Merge using a flat min-heap (backed by typed lists
heapValuesandheapChunkIndicesto avoid object allocation GC overhead).
Configuration & Parameters
As a package library, configuration is handled via function parameters:
API Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
signed |
bool |
true |
Tells radixSortInt whether to treat the list as signed or unsigned. |
ascending |
bool |
true |
If false, reverses the sorted output in-place at the end. |
reuseBuffer |
bool |
true |
Uses pooled buffers to reduce memory GC allocation cycles. |
threads |
int? |
null |
Number of isolates to spawn (auto-calculates if null). |
nanPlacement |
String |
'end' |
Placement of NaN in floats ('start', 'end', 'remove'). |
maxBitLength |
int |
N/A | Bit length parameter constraint for range-optimized BigInt sorting. |
Contributing
Contributions are welcome! Here’s how to get started:
- Fork the repository.
- Create a new branch:
git checkout -b feature/YourFeature - Commit your changes:
git commit -m "Add amazing feature" - Push to your branch:
git push origin feature/YourFeature - Open a pull request.
💡 Please read our Contributing Guidelines and open an issue first for major feature ideas or changes.
⚖️ License
This project is dual-licensed:
-
Open Source License: GPL-3.0
- Free to use, modify, and distribute under GPL terms.
- Any distributed modified version must also be GPL-3.0.
-
Commercial License:
- Required for using the library in proprietary / closed-source products.
- Only available from the copyright holder (Mostafa Mahmoud).
- Contact: mostafasensei106@gmail.com
Made with ❤️ by MostafaSensei106
Libraries
- radix_plus
- radix_Plus