mirror of
https://github.com/roc-lang/roc.git
synced 2025-07-17 11:35:00 +00:00
163 lines
4.8 KiB
Rust
163 lines
4.8 KiB
Rust
#[path = "../src/helpers/mod.rs"]
|
|
mod helpers;
|
|
|
|
// defines roc_alloc and friends
|
|
pub use helpers::platform_functions::*;
|
|
|
|
use bumpalo::Bump;
|
|
use criterion::{black_box, criterion_group, criterion_main, Criterion};
|
|
use roc_gen_llvm::{llvm::build::LlvmBackendMode, run_roc::RocCallResult, run_roc_dylib};
|
|
use roc_mono::ir::OptLevel;
|
|
use roc_std::RocList;
|
|
|
|
// results April 9, 2023
|
|
//
|
|
// > pure roc quicksort time: [106.97 us 107.27 us 107.63 us]
|
|
// > roc zig quicksort time: [34.765 us 35.301 us 35.865 us]
|
|
// > rust std sort time: [20.413 us 20.623 us 20.838 us]
|
|
|
|
type Input = RocList<i64>;
|
|
type Output = RocList<i64>;
|
|
|
|
type Main<I, O> = unsafe extern "C" fn(I, *mut RocCallResult<O>);
|
|
|
|
const ZIG_ROC_QUICKSORT: &str = indoc::indoc!(
|
|
r#"
|
|
app "bench" provides [main] to "./platform"
|
|
|
|
main : List I64 -> List I64
|
|
main = \originalList -> List.sortAsc originalList
|
|
"#
|
|
);
|
|
|
|
const PURE_ROC_QUICKSORT: &str = indoc::indoc!(
|
|
r#"
|
|
app "bench" provides [main] to "./platform"
|
|
|
|
main : List I64 -> List I64
|
|
main = \originalList ->
|
|
n = List.len originalList
|
|
|
|
quicksortHelp originalList 0 (n - 1)
|
|
|
|
quicksortHelp : List (Num a), U64, U64 -> List (Num a)
|
|
quicksortHelp = \list, low, high ->
|
|
if low < high then
|
|
when partition low high list is
|
|
Pair partitionIndex partitioned ->
|
|
partitioned
|
|
|> quicksortHelp low (partitionIndex - 1)
|
|
|> quicksortHelp (partitionIndex + 1) high
|
|
else
|
|
list
|
|
|
|
partition : U64, U64, List (Num a) -> [Pair U64 (List (Num a))]
|
|
partition = \low, high, initialList ->
|
|
when List.get initialList high is
|
|
Ok pivot ->
|
|
when partitionHelp low low initialList high pivot is
|
|
Pair newI newList ->
|
|
Pair newI (List.swap newList newI high)
|
|
|
|
Err _ ->
|
|
Pair low initialList
|
|
|
|
partitionHelp : U64, U64, List (Num c), U64, Num c -> [Pair U64 (List (Num c))]
|
|
partitionHelp = \i, j, list, high, pivot ->
|
|
if j < high then
|
|
when List.get list j is
|
|
Ok value ->
|
|
if value <= pivot then
|
|
partitionHelp (i + 1) (j + 1) (List.swap list i j) high pivot
|
|
else
|
|
partitionHelp i (j + 1) list high pivot
|
|
|
|
Err _ ->
|
|
Pair i list
|
|
else
|
|
Pair i list
|
|
"#
|
|
);
|
|
|
|
fn roc_function<'a>(
|
|
arena: &'a Bump,
|
|
source: &str,
|
|
) -> libloading::Symbol<'a, Main<*mut Input, Output>> {
|
|
let config = helpers::llvm::HelperConfig {
|
|
mode: LlvmBackendMode::GenTest,
|
|
ignore_problems: false,
|
|
emit_debug_info: true,
|
|
opt_level: OptLevel::Optimize,
|
|
};
|
|
|
|
let context = inkwell::context::Context::create();
|
|
let (main_fn_name, errors, lib) = helpers::llvm::helper(
|
|
arena,
|
|
config,
|
|
source,
|
|
arena.alloc(context),
|
|
roc_load::FunctionKind::LambdaSet,
|
|
);
|
|
|
|
assert!(errors.is_empty(), "Encountered errors:\n{errors}");
|
|
|
|
run_roc_dylib!(arena.alloc(lib), main_fn_name, *mut Input, Output)
|
|
}
|
|
|
|
pub fn criterion_benchmark(c: &mut Criterion) {
|
|
let arena = Bump::new();
|
|
|
|
let pure_roc_quicksort_main = roc_function(&arena, PURE_ROC_QUICKSORT);
|
|
let roc_zig_quicksort_main = roc_function(&arena, ZIG_ROC_QUICKSORT);
|
|
|
|
let input_numbers: Vec<_> = std::iter::repeat([1, 2, 3, 4, 5, 6, 7, 8])
|
|
.flatten()
|
|
.take(1000)
|
|
.collect();
|
|
|
|
let input = arena.alloc(RocList::from_slice(&input_numbers));
|
|
|
|
c.bench_function("pure roc quicksort", |b| {
|
|
b.iter(|| unsafe {
|
|
let mut main_result = RocCallResult::default();
|
|
|
|
assert!(input.is_unique());
|
|
|
|
// reset_input
|
|
input.copy_from_slice(&input_numbers);
|
|
|
|
pure_roc_quicksort_main(black_box(input), &mut main_result);
|
|
})
|
|
});
|
|
|
|
c.bench_function("roc zig quicksort", |b| {
|
|
b.iter(|| unsafe {
|
|
let mut main_result = RocCallResult::default();
|
|
|
|
assert!(input.is_unique());
|
|
|
|
// reset_input
|
|
input.copy_from_slice(&input_numbers);
|
|
|
|
roc_zig_quicksort_main(black_box(input), &mut main_result);
|
|
})
|
|
});
|
|
|
|
c.bench_function("rust std sort", |b| {
|
|
b.iter(|| unsafe {
|
|
assert!(input.is_unique());
|
|
|
|
// reset_input
|
|
input.copy_from_slice(&input_numbers);
|
|
|
|
// an attempt to block optimizing based on the input list
|
|
let ptr = black_box(input.as_mut_ptr());
|
|
let input = std::slice::from_raw_parts_mut(ptr, 1000);
|
|
|
|
input.sort()
|
|
})
|
|
});
|
|
}
|
|
|
|
criterion_group!(quicksort_benches, criterion_benchmark);
|
|
criterion_main!(quicksort_benches);
|