From 8720cd14e530d6ec45f8a40634a7752cb852cca4 Mon Sep 17 00:00:00 2001 From: Jack O'Connor Date: Fri, 15 Aug 2025 19:11:45 +0100 Subject: [PATCH 1/2] POC: Use Rust's `sort_by` instead of `timsort::try_sort_by_gt` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Time improvements **rust-timsort** (Timing from Linux laptop - I didn't repeat as 16 mins long) ```sh ✦ ❯ time cargo run --release -- -c "from random import random; sorted([random() for i in range(1_000_000)]); print('DONE');" Finished `release` profile [optimized] target(s) in 0.16s Running `target/release/rustpython -c 'from random import random; sorted([random() for i in range(1_000_000)]); print('\''DONE'\'');'` DONE real 16m52.217s user 16m51.926s sys 0m0.174s ``` **Built-in** (Timing from MacOS laptop) ```sh ❯ time cargo run --release -- -c "from random import random; sorted([random() for i in range(1_000_000)]); print('DONE');" Finished `release` profile [optimized] target(s) in 0.89s Running `target/release/rustpython -c 'from random import random; sorted([random() for i in range(1_000_000)]); print('\''DONE'\'');'` DONE cargo run --release -- -c 0.96s user 0.23s system 54% cpu 2.196 total ``` ## Verify list is sorted ```sh ❯ cargo run --release -- -c "from random import random; l = sorted([random() for i in range(1_000_000)]); print(all(l[i] <= l[i+1] for i in range(len(l) - 1)) ─╯ );" TRUE ``` ## TODO - This uses `.unwrap` because I don't know how to handle the error case - This doesn't use Ordering::Equal so it needs to either be confirmed that this is a stable sorting algorithm, or else make it stable --- vm/src/builtins/list.rs | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/vm/src/builtins/list.rs b/vm/src/builtins/list.rs index 9a7b589418..dd7b55af1c 100644 --- a/vm/src/builtins/list.rs +++ b/vm/src/builtins/list.rs @@ -504,6 +504,7 @@ impl Representable for PyList { } } +use std::cmp::Ordering; fn do_sort( vm: &VirtualMachine, values: &mut Vec, @@ -515,17 +516,26 @@ fn do_sort( } else { PyComparisonOp::Gt }; - let cmp = |a: &PyObjectRef, b: &PyObjectRef| a.rich_compare_bool(b, op, vm); + let cmp = |a: &PyObjectRef, b: &PyObjectRef| { + let res = a.rich_compare_bool(b, op, vm).unwrap(); + if res { + Ordering::Greater + } else { + Ordering::Less + } + }; if let Some(ref key_func) = key_func { let mut items = values .iter() .map(|x| Ok((x.clone(), key_func.call((x.clone(),), vm)?))) .collect::, _>>()?; - timsort::try_sort_by_gt(&mut items, |a, b| cmp(&a.1, &b.1))?; + // timsort::try_sort_by_gt(&mut items, |a, b| cmp(&a.1, &b.1))?; + items.sort_by(|a, b| cmp(&a.1, &b.1)); *values = items.into_iter().map(|(val, _)| val).collect(); } else { - timsort::try_sort_by_gt(values, cmp)?; + // timsort::try_sort_by_gt(values, cmp)?; + values.sort_by(|a, b| cmp(a, b)); } Ok(()) From 8b909c36c2c228eba2cae91c85a7c61e616947bc Mon Sep 17 00:00:00 2001 From: Jack O'Connor Date: Sat, 16 Aug 2025 17:40:31 +0100 Subject: [PATCH 2/2] POC: Return Ordering::Equal if exception and see what happens --- vm/src/builtins/list.rs | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/vm/src/builtins/list.rs b/vm/src/builtins/list.rs index dd7b55af1c..738ded2a31 100644 --- a/vm/src/builtins/list.rs +++ b/vm/src/builtins/list.rs @@ -517,11 +517,9 @@ fn do_sort( PyComparisonOp::Gt }; let cmp = |a: &PyObjectRef, b: &PyObjectRef| { - let res = a.rich_compare_bool(b, op, vm).unwrap(); - if res { - Ordering::Greater - } else { - Ordering::Less + match a.rich_compare_bool(b, op, vm) { + Ok(res) => if res { Ordering::Greater } else { Ordering::Less }, + Err(_) => Ordering::Equal, } };