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

rustc_metadata: replace Entry table with one table for each of its fields (AoS -> SoA). #59953

Merged
merged 13 commits into from
Oct 17, 2019

Conversation

eddyb
Copy link
Member

@eddyb eddyb commented Apr 14, 2019

In #59789 (comment) I noticed that for many cross-crate queries (e.g. predicates_of(def_id)), we were deserializing the rustc_metadata::schema::Entry for def_id only to read one field (i.e. predicates).

But there are several such queries, and Entry is not particularly small (in terms of number of fields, the encoding itself is quite compact), so there is a large (and unnecessary) constant factor.

This PR replaces the (random-access) array¹ of Entry structures ("AoS"), with many separate arrays¹, one for each field that used to be in Entry ("SoA"), resulting in the ability to read individual fields separately, with negligible time overhead (in thoery), and some size overhead (as these arrays are not sparse).

In a way, the new approach is closer to incremental on-disk caches, which store each query's cached results separately, but it would take significantly more work to unify the two.

For stage1 libcore's metadata blob, the size overhead is 8.44%, and I have another commit (not initially included because I want to do perf runs with both EDIT: added it now) that brings it down to 5.88%.

¹(in the source, these arrays are called "tables", but perhaps they could use a better name)

@rust-highfive
Copy link
Collaborator

r? @zackmdavis

(rust_highfive has picked a reviewer for you, use r? to override)

@rust-highfive rust-highfive added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Apr 14, 2019
@eddyb
Copy link
Member Author

eddyb commented Apr 14, 2019

r? @michaelwoerister cc @Zoxc @nnethercote

@bors try

@bors
Copy link
Contributor

bors commented Apr 14, 2019

⌛ Trying commit 1ab0e24 with merge 3919374...

bors added a commit that referenced this pull request Apr 14, 2019
 rustc_metadata: replace Entry table with one table for each of its fields (AoS -> SoA).

In #59789 (comment) I noticed that for many cross-crate queries (e.g. `predicates_of(def_id)`), we were deserializing the `rustc_metadata::schema::Entry` for `def_id` *only* to read one field (i.e. `predicates`).

But there are several such queries, and `Entry` is not particularly small (in terms of number of fields, the encoding itself is quite compact), so there is a large (and unnecessary) constant factor.

This PR replaces the (random-access) array¹ of `Entry` structures ("AoS"), with many separate arrays¹, one for each field that used to be in `Entry` ("SoA"), resulting in the ability to read individual fields separately, with negligible time overhead (in thoery), and some size overhead (as these arrays are not sparse).

For stage1 `libcore`'s metadata blob, the size overhead is `8.44%`, and I have another commit (not initially included in this PR because I want to do perf runs with both) that brings it down to `5.88%`.

¹(in the source, these arrays are called "tables", but perhaps they could use a better name)
@bors
Copy link
Contributor

bors commented Apr 14, 2019

☀️ Try build successful - checks-travis
Build commit: 3919374

@Zoxc
Copy link
Contributor

Zoxc commented Apr 14, 2019

@rust-timer build 3919374

@rust-timer
Copy link
Collaborator

Success: Queued 3919374 with parent 0085672, comparison URL.

@rust-timer
Copy link
Collaborator

Finished benchmarking try commit 3919374

@Zoxc
Copy link
Contributor

Zoxc commented Apr 14, 2019

Performance looks good except for webrender-check.

@nnethercote
Copy link
Contributor

Performance looks good except for webrender-check.

Can you please be more specific with your performance comments?

Instruction counts for everything look great, including webrender-check. Wall-time for webrender-check check-incremental builds has a 28% regression but almost everything else (including other webrender workloads) is a clear improvement. I wonder if that's a fluky bad measurement. Even if it's not, I think this PR is a clear win overall.

@eddyb
Copy link
Member Author

eddyb commented Apr 14, 2019

@Zoxc Oh, wow, that's a huge gap between instructions and cycles.
I wonder if it's the extra memory being used, that's causing that.
I really wish I had cache misses on there, it would make things clearer.

Also, I've pushed the extra commit I mentioned in the PR description, let's see what that does!

@bors try

@bors
Copy link
Contributor

bors commented Apr 14, 2019

⌛ Trying commit a173ddc with merge 0403760...

bors added a commit that referenced this pull request Apr 14, 2019
 rustc_metadata: replace Entry table with one table for each of its fields (AoS -> SoA).

*Based on top of #59887*

In #59789 (comment) I noticed that for many cross-crate queries (e.g. `predicates_of(def_id)`), we were deserializing the `rustc_metadata::schema::Entry` for `def_id` *only* to read one field (i.e. `predicates`).

But there are several such queries, and `Entry` is not particularly small (in terms of number of fields, the encoding itself is quite compact), so there is a large (and unnecessary) constant factor.

This PR replaces the (random-access) array¹ of `Entry` structures ("AoS"), with many separate arrays¹, one for each field that used to be in `Entry` ("SoA"), resulting in the ability to read individual fields separately, with negligible time overhead (in thoery), and some size overhead (as these arrays are not sparse).

In a way, the new approach is closer to incremental on-disk caches, which store each query's cached results separately, but it would take significantly more work to unify the two.

For stage1 `libcore`'s metadata blob, the size overhead is `8.44%`, and I have another commit (not initially included in this PR because I want to do perf runs with both) that brings it down to `5.88%`.

¹(in the source, these arrays are called "tables", but perhaps they could use a better name)
@bors
Copy link
Contributor

bors commented Apr 14, 2019

☀️ Try build successful - checks-travis
Build commit: 0403760

@eddyb
Copy link
Member Author

eddyb commented Apr 14, 2019

@rust-timer build 0403760

@rust-timer
Copy link
Collaborator

Success: Queued 0403760 with parent 60076bb, comparison URL.

@rust-timer
Copy link
Collaborator

Finished benchmarking try commit 0403760

@michaelwoerister
Copy link
Member

Thanks a lot for the PR, @eddyb! Looks like a nice improvement.
This is a bigger changeset than I thought. I'll review soonish :)

@eddyb
Copy link
Member Author

eddyb commented Apr 15, 2019

Keep in mind most commits are refactors that don't change the encoded metadata (or do so without changing its size).
The last two are the most interesting ones wrt this change. Oh and the diff is large in part because indentation/syntax changes.

@eddyb
Copy link
Member Author

eddyb commented Apr 15, 2019

@Zoxc looks like the latest numbers are better?
(I haven't checked yet between the two builds (for the last 2 commits), and webrender-check may have been spurious, not sure)

@Zoxc
Copy link
Contributor

Zoxc commented Apr 15, 2019

It's possible, webrender-debug or webrender-opt didn't regress which would be expected if webrender-check did.

@eddyb
Copy link
Member Author

eddyb commented Apr 16, 2019

Ugh, these numbers are poisoned by the huge delta in 0085672...60076bb.

I'll have to open another PR for the version without the last commit, and start the try builds at the same time...

@bors
Copy link
Contributor

bors commented Oct 15, 2019

⌛ Trying commit d89dddc with merge b2a5ec95e0c4044dafb3cc99fcf71c2db186bb42...

@bors
Copy link
Contributor

bors commented Oct 15, 2019

☀️ Try build successful - checks-azure
Build commit: b2a5ec95e0c4044dafb3cc99fcf71c2db186bb42 (b2a5ec95e0c4044dafb3cc99fcf71c2db186bb42)

@Centril
Copy link
Contributor

Centril commented Oct 15, 2019

@rust-timer build b2a5ec95e0c4044dafb3cc99fcf71c2db186bb42

@rust-timer
Copy link
Collaborator

Queued b2a5ec95e0c4044dafb3cc99fcf71c2db186bb42 with parent 437ca55, future comparison URL.

@rust-timer
Copy link
Collaborator

Finished benchmarking try commit b2a5ec95e0c4044dafb3cc99fcf71c2db186bb42, comparison URL.

@eddyb
Copy link
Member Author

eddyb commented Oct 16, 2019

Before (437ca55)
rust-std.tar.xz
After (b2a5ec95e0c4044dafb3cc99fcf71c2db186bb42)
rust-std.tar.xz
Increase
libcore.rlib 24.37MB 25.85MB 6.1%
libstd.rlib 9.64MB 10.12MB 5.0%
Total 175.12MB 177.22MB 1.2%

(Note that the total is compressed with XZ, but also includes librustc*, soon to be in a separate rustc-dev component)

@michaelwoerister
Copy link
Member

Thanks, @eddyb!

@bors r+

@bors
Copy link
Contributor

bors commented Oct 17, 2019

📌 Commit d89dddc has been approved by michaelwoerister

@bors bors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Oct 17, 2019
@michaelwoerister
Copy link
Member

@bors rollup=never

@petrochenkov petrochenkov self-assigned this Oct 17, 2019
@bors
Copy link
Contributor

bors commented Oct 17, 2019

⌛ Testing commit d89dddc with merge ea45150...

bors added a commit that referenced this pull request Oct 17, 2019
 rustc_metadata: replace Entry table with one table for each of its fields (AoS -> SoA).

In #59789 (comment) I noticed that for many cross-crate queries (e.g. `predicates_of(def_id)`), we were deserializing the `rustc_metadata::schema::Entry` for `def_id` *only* to read one field (i.e. `predicates`).

But there are several such queries, and `Entry` is not particularly small (in terms of number of fields, the encoding itself is quite compact), so there is a large (and unnecessary) constant factor.

This PR replaces the (random-access) array¹ of `Entry` structures ("AoS"), with many separate arrays¹, one for each field that used to be in `Entry` ("SoA"), resulting in the ability to read individual fields separately, with negligible time overhead (in thoery), and some size overhead (as these arrays are not sparse).

In a way, the new approach is closer to incremental on-disk caches, which store each query's cached results separately, but it would take significantly more work to unify the two.

For stage1 `libcore`'s metadata blob, the size overhead is `8.44%`, and I have another commit (~~not initially included because I want to do perf runs with both~~ **EDIT**: added it now) that brings it down to `5.88%`.

¹(in the source, these arrays are called "tables", but perhaps they could use a better name)
@petrochenkov petrochenkov removed their assignment Oct 17, 2019
@bors
Copy link
Contributor

bors commented Oct 17, 2019

☀️ Test successful - checks-azure
Approved by: michaelwoerister
Pushing ea45150 to master...

@bors bors added the merged-by-bors This PR was explicitly merged by bors. label Oct 17, 2019
@bors bors merged commit d89dddc into rust-lang:master Oct 17, 2019
@eddyb eddyb deleted the soa-metadata branch October 17, 2019 15:08
JohnTitor added a commit to JohnTitor/rust that referenced this pull request Oct 22, 2019
…ables, r=michaelwoerister

rustc_metadata: use a table for super_predicates, fn_sig, impl_trait_ref.

This is an attempt at a part of rust-lang#65407, i.e. moving parts of cross-crate "metadata" into tables that match queries more closely.

Three new tables should be enough to see some perf/metadata size changes.
(need to do something similar to rust-lang#59953 (comment))

There are other bits of data that could be made into tables, but they can be more compact so the impact would likely be not as bad, and they're also more work to set up.
Centril added a commit to Centril/rust that referenced this pull request Oct 23, 2019
…ables, r=michaelwoerister

rustc_metadata: use a table for super_predicates, fn_sig, impl_trait_ref.

This is an attempt at a part of rust-lang#65407, i.e. moving parts of cross-crate "metadata" into tables that match queries more closely.

Three new tables should be enough to see some perf/metadata size changes.
(need to do something similar to rust-lang#59953 (comment))

There are other bits of data that could be made into tables, but they can be more compact so the impact would likely be not as bad, and they're also more work to set up.
Centril added a commit to Centril/rust that referenced this pull request Oct 23, 2019
…ables, r=michaelwoerister

rustc_metadata: use a table for super_predicates, fn_sig, impl_trait_ref.

This is an attempt at a part of rust-lang#65407, i.e. moving parts of cross-crate "metadata" into tables that match queries more closely.

Three new tables should be enough to see some perf/metadata size changes.
(need to do something similar to rust-lang#59953 (comment))

There are other bits of data that could be made into tables, but they can be more compact so the impact would likely be not as bad, and they're also more work to set up.
tmandry added a commit to tmandry/rust that referenced this pull request Nov 27, 2019
…imulacrum

rustc_metadata: simplify the interactions between Lazy and Table.

These are small post-rust-lang#59953 cleanups (including undoing some contrivances from that PR).

r? @michaelwoerister
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
merged-by-bors This PR was explicitly merged by bors. S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet