-
Notifications
You must be signed in to change notification settings - Fork 12.8k
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
Overhaul syntax::fold::Folder
.
#58061
Conversation
@bors try |
⌛ Trying commit b4a6b98fb425e66926941efa55dce39aea400914 with merge 4d27e368a336fc53353c891ee0dc425399c612c0... |
@nnethercote |
☀️ Test successful - checks-travis |
I hadn't seen #57662. It's definitely overlapping with this PR. Notable differences, judging from a quick skim:
|
The reason the new approach is faster is that an existing noop fold overwrites all the nodes with the same values. There are no reallocations due to the use of |
@rust-timer build 4d27e368a336fc53353c891ee0dc425399c612c0 |
Success: Queued 4d27e368a336fc53353c891ee0dc425399c612c0 with parent 23d8d0c, comparison URL. |
Finished benchmarking try commit 4d27e368a336fc53353c891ee0dc425399c612c0 |
The perf results are similar to what I saw locally. Widespread improvements, mostly on "clean incremental" runs, with a best result of -3.4%. |
Comparing this PR with #57662 some more, the handling of the The handling of the other cases is where the differences are bigger. This PR keeps the existing structure for ones like In contrast, #57662 introduces the |
A final summary! This PR:
Overall, I think this PR is more complete while involving less changes. But I'm biased :) Let me know if I've gotten any of the details wrong. |
b4a6b98
to
d05b178
Compare
I have updated the code. It's now complete except for one thing: as the "njn:" comment in the code says, I think the r? @petrochenkov: the code is ready to review, but as well as making the main change, I have made a bunch of minor clean-ups. If you like I could pull out those clean-ups into separate commits preceding the main commit. |
Great work, thanks. I think I prefer this PRs trajectory. Why:
|
Regarding naming. |
If that's not too annoying, could you split the PR into two commits
|
d05b178
to
f9d6e3e
Compare
Specifically: - Remove dead methods: fold_usize, fold_meta_items, fold_opt_bounds. - Remove useless methods: fold_global_asm, fold_range_end. - Inline and remove unnecessary methods: fold_item_simple, fold_foreign_item_simple.
It doesn't need to return an `Option`.
It's simpler that way.
By eliminating some unnecessary methods, and moving/renaming some functions that look like they might be methods but aren't.
f9d6e3e
to
3263f02
Compare
@petrochenkov: the new code is up.
|
The usual solution is to move the file renaming into a separate commit. |
r=me with the file renaming moved into a separate commit or without it. |
This commit changes `syntax::fold::Folder` from a functional style (where most methods take a `T` and produce a new `T`) to a more imperative style (where most methods take and modify a `&mut T`), and renames it `syntax::mut_visit::MutVisitor`. The first benefit is speed. The functional style does not require any reallocations, due to the use of `P::map` and `MoveMap::move_{,flat_}map`. However, every field in the AST must be overwritten; even those fields that are unchanged are overwritten with the same value. This causes a lot of unnecessary memory writes. The imperative style reduces instruction counts by 1--3% across a wide range of workloads, particularly incremental workloads. The second benefit is conciseness; the imperative style is usually more concise. E.g. compare the old functional style: ``` fn fold_abc(&mut self, abc: ABC) { ABC { a: fold_a(abc.a), b: fold_b(abc.b), c: abc.c, } } ``` with the imperative style: ``` fn visit_abc(&mut self, ABC { a, b, c: _ }: &mut ABC) { visit_a(a); visit_b(b); } ``` (The reductions get larger in more complex examples.) Overall, the patch removes over 200 lines of code -- even though the new code has more comments -- and a lot of the remaining lines have fewer characters. Some notes: - The old style used methods called `fold_*`. The new style mostly uses methods called `visit_*`, but there are a few methods that map a `T` to something other than a `T`, which are called `flat_map_*` (`T` maps to multiple `T`s) or `filter_map_*` (`T` maps to 0 or 1 `T`s). - `move_map.rs`/`MoveMap`/`move_map`/`move_flat_map` are renamed `map_in_place.rs`/`MapInPlace`/`map_in_place`/`flat_map_in_place` to reflect their slightly changed signatures. - Although this commit renames the `fold` module as `mut_visit`, it keeps it in the `fold.rs` file, so as not to confuse git. The next commit will rename the file.
3263f02
to
bfcbd23
Compare
Thank you for the suggestion, I did that. @bors r=petrochenkov |
📌 Commit bfcbd23 has been approved by |
…nkov Overhaul `syntax::fold::Folder`. This PR changes `syntax::fold::Folder` from a functional style (where most methods take a `T` and produce a new `T`) to a more imperative style (where most methods take and modify a `&mut T`), and renames it `syntax::mut_visit::MutVisitor`. This makes the code faster and more concise.
☀️ Test successful - checks-travis, status-appveyor |
Make `visit_clobber`'s impl safe This was originally introduced in rust-lang#58061 but I didn't see any perf discussion about it, so let's see what perf says. r? `@nnethercote`
Make `visit_clobber`'s impl safe This was originally introduced in rust-lang#58061 but I didn't see any perf discussion about it, so let's see what perf says. r? `@nnethercote`
This PR changes
syntax::fold::Folder
from a functional style(where most methods take a
T
and produce a newT
) to a moreimperative style (where most methods take and modify a
&mut T
), andrenames it
syntax::mut_visit::MutVisitor
.This makes the code faster and more concise.