Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

experiment with rpds vectors #2057

Draft
wants to merge 3 commits into
base: master
Choose a base branch
from
Draft

experiment with rpds vectors #2057

wants to merge 3 commits into from

Conversation

jneem
Copy link
Member

@jneem jneem commented Sep 27, 2024

This is an experiment regarding array performance. Our current array representation (as essentially a Rc<[RichTerm]>) is problematic because it makes many common operations unnecessarily quadratic. This PR replaces it with a rpds::Vector<RichTerm> in reverse order, and the initial benchmarks look promising.

In more detail, the current arrays have a few performance characteristics that we might like to keep:

  • constant-time random access
  • constant-time slicing
  • some amount of memory sharing
    The main problem is that there's no constant-time "cons" operation, and the concatenation operator xs @ ys is O(xs.len() + ys.len()). This makes many functional-style list functions (like the stdlib implementations of reverse and filter) quadratic in the length of their input.

The Vector implementation in the rpds crate is a "persistent vector" aka "bitmapped vector trie", which offers persistence/sharing, fast random access, and fast appends. We can do the same slicing trick that we're current using for Rc<[RichTerm]> to also add fast slicing. Thanks to fast appends, we can do concatenation xs @ ys in O(ys.len()) time (provided that there are no contracts that need to be applied to xs; I'm also ignoring logarithmic terms). This is backwards from the more common concatenation pattern in functional languages, so we store arrays backwards in order to get time O(xs.len()) instead. (We could achieve the minimum of the two by storing an array as two Vectors, a backwards one followed by a forwards one.)

There are a few ways in which rpds::Vector isn't a perfect fit:

  • it insists on wrapping the vector elements in Arc or Rc, which we don't want because RichTerm already has a shared pointer
  • it doesn't support many of the optimizations we had for arrays with a single reference
  • there's no fast iteration over slices (it's linear in the number of elements you skip at the beginning)

Despite these, this PR gives a 35% improvement in random normal, and a few other improvements between 10 and 20%. I'd like to also try benchmarking im and/or imbl.

@github-actions github-actions bot temporarily deployed to pull request September 27, 2024 15:49 Inactive
Copy link
Contributor

github-actions bot commented Sep 27, 2024

🐰 Bencher Report

Branch2057/merge
Testbedubuntu-latest

⚠️ WARNING: The following Measure does not have a Threshold. Without a Threshold, no Alerts will ever be generated!

Click here to create a new Threshold
For more information, see the Threshold documentation.
To only post results if a Threshold exists, set the --ci-only-thresholds CLI flag.

Click to view all benchmark results
BenchmarkLatencynanoseconds (ns)
fibonacci 10📈 view plot
⚠️ NO THRESHOLD
491,340.00
pidigits 100📈 view plot
⚠️ NO THRESHOLD
3,213,800.00
product 30📈 view plot
⚠️ NO THRESHOLD
761,460.00
scalar 10📈 view plot
⚠️ NO THRESHOLD
1,438,600.00
sum 30📈 view plot
⚠️ NO THRESHOLD
757,840.00
🐰 View full continuous benchmarking report in Bencher

@yannham
Copy link
Member

yannham commented Sep 27, 2024

I'll see what it gives on the private benchmark

@github-actions github-actions bot temporarily deployed to pull request September 27, 2024 16:25 Inactive
@github-actions github-actions bot temporarily deployed to pull request September 27, 2024 16:50 Inactive
@jneem
Copy link
Member Author

jneem commented Sep 30, 2024

I tried out imbl, but the performance is worse than rpds.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants