-
Notifications
You must be signed in to change notification settings - Fork 124
perf: improve @list.from_iter use one pass #2036
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
base: main
Are you sure you want to change the base?
Conversation
New implementation avoids unnecessary list reversal but uses more memory with two pointersCategory The abort case seems unreachable but could be more explicitCategory Complex pointer manipulation logic could benefit from additional commentsCategory // Initialize list if empty
(Empty, _) => {...}
// Append new element to tail
(More(_), More(_) as ptr_) => {...} Reasoning |
Pull Request Test Coverage Report for Build 7002Details
💛 - Coveralls |
1d7b264
to
46f7cdf
Compare
46f7cdf
to
4f6022e
Compare
How's the performance comparison? |
bench resultillu@illusory0x0 ~/d/b/moon-bench (master)> moon bench --target wasm,native
bench username/hello/top.mbt::0
name time (mean ± σ) range (min … max)
v1 45.83 µs ± 1.32 µs 45.11 µs … 49.47 µs in 10 × 2196 runs
v2 49.36 µs ± 0.28 µs 49.06 µs … 49.95 µs in 10 × 2037 runs
Total tests: 1, passed: 1, failed: 0. [wasm]
bench username/hello/top.mbt::0
name time (mean ± σ) range (min … max)
v1 27.75 µs ± 0.17 µs 27.60 µs … 28.12 µs in 10 × 3636 runs
v2 28.79 µs ± 0.49 µs 28.23 µs … 29.56 µs in 10 × 3402 runs
Total tests: 1, passed: 1, failed: 0. [native]
Examplepub enum T[A] {
Empty
More(A, mut tail~ : T[A])
} derive(Eq)
pub fn from_iter_v1[A](iter : Iter[A]) -> T[A] {
let mut res = Empty
let mut ptr = Empty
for x in iter {
match (res, ptr) {
(Empty, _) => {
res = More(x, tail=Empty)
ptr = res
}
(More(_), More(_) as ptr_) => {
ptr_.tail = More(x, tail=Empty)
ptr = ptr_.tail
}
(_, _) => abort("unreachable")
}
}
res
}
pub fn from_iter_v2[A](iter : Iter[A]) -> T[A] {
iter.fold(init=Empty, fn(acc, e) { More(e, tail=acc) }).reverse_inplace()
}
fn reverse_inplace[A](self : T[A]) -> T[A] {
match self {
Empty | More(_, tail=Empty) => self
More(head, tail~) =>
loop More(head, tail=Empty), tail {
result, Empty => result
result, More(_, tail=xs) as new_result => {
new_result.tail = result
continue new_result, xs
}
}
}
}
test (b : @bench.T) {
let xs = Int::until(0,1000)
b.bench(name="v1",fn() { b.keep(from_iter_v1(xs)) })
b.bench(name="v2",fn() { b.keep(from_iter_v2(xs)) })
}
|
b59e88b
to
869e957
Compare
It looks drastically faster on wasm-gc. Seems to be a reasonable change. |
benchmark result is unstable in js backend and wasm-gc backend due to GC. |
@peter-jerry-ye Should we close this PR since this change is a weak performance boost? |
No description provided.