Skip to content

Conversation

dtolnay
Copy link
Member

@dtolnay dtolnay commented Aug 13, 2018

Two new insta-stable impls in libproc_macro:

impl Extend<TokenTree> for TokenStream
impl Extend<TokenStream> for TokenStream

proc_macro::TokenStream already implements FromIterator<TokenTree> and FromIterator<TokenStream> so I elected to support the same input types for Extend.

This commit reduces compile time of Serde derives by 60% (takes less than half as long to compile) as measured by building our test suite:

$ git clone https://github.com/serde-rs/serde
$ cd serde/test_suite
$ cargo check --tests --features proc-macro2/nightly
$ rm -f ../target/debug/deps/libtest_*.rmeta
$ time cargo check --tests --features proc-macro2/nightly
Before: 20.8 seconds
After: 8.6 seconds

r? @alexcrichton

@rust-highfive rust-highfive added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Aug 13, 2018
@dtolnay
Copy link
Member Author

dtolnay commented Aug 13, 2018

Requires dtolnay/proc-macro2#114 in order to see the performance improvement.

offset: 0,
len: vec.len() as u32,
data: Lrc::new(vec),
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could this delegate to new_preserving_capacity after the shrink_to_fit?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

vec.truncate(self.offset as usize + self.len as usize);
// Drop any elements before our view of the data.
if self.offset != 0 {
vec.drain(..self.offset as usize);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Switching these two may be a bit more readable perhaps?

vec.drain(..self.offset as usize);
vec.truncate(self.len as usize);

Additionally, how come the drain is conditional?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I removed the conditional but I kept the order of truncate first then drain. I added a comment to explain -- draining first would involve unnecessarily shifting all the vector elements that are past the end of the current rc's view of the data.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Aha makes sense 👍

@alexcrichton
Copy link
Member

@bors: delegate=dtolnay

Looks great to me, very nice find! r=me with a few nits, and otherwise cc @rust-lang/libs, @nrc, and @petrochenkov on the API addition here.

@bors
Copy link
Collaborator

bors commented Aug 13, 2018

✌️ @dtolnay can now approve this pull request

@dtolnay
Copy link
Member Author

dtolnay commented Aug 14, 2018

@bors r+

@bors
Copy link
Collaborator

bors commented Aug 14, 2018

📌 Commit 69b9c23 has been approved by dtolnay

@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-review Status: Awaiting review from the assignee but also interested parties. labels Aug 14, 2018
@BurntPizza
Copy link
Contributor

@dtolnay I'd like to hear how you found this; just profiling while building a serde project?

@dtolnay
Copy link
Member Author

dtolnay commented Aug 14, 2018

@BurntPizza no profiling involved this time, although that would have revealed the problem. I think I've built enough of Serde / syn / quote / proc-macro2 to know where the skeletons are hidden and I finally got a chance to pursue this one.

The original code in alexcrichton/proc-macro2#114 performs a quadratic amount of memory allocation and copying when called the way quote! ends up calling it. I had brought up the need for Extend in #38356 (comment) during the design phase of Syn 0.14 and the quadratic approach was done as a stopgap until the impl could be written.

@BurntPizza
Copy link
Contributor

Ah, the "Because I'm a guru" methodology.
I wish I could apply it more often myself. ;)

@bors
Copy link
Collaborator

bors commented Aug 16, 2018

⌛ Testing commit 69b9c23 with merge b559042...

bors added a commit that referenced this pull request Aug 16, 2018
TokenStream::extend

Two new insta-stable impls in libproc_macro:

```rust
impl Extend<TokenTree> for TokenStream
impl Extend<TokenStream> for TokenStream
```

`proc_macro::TokenStream` already implements `FromIterator<TokenTree>` and `FromIterator<TokenStream>` so I elected to support the same input types for `Extend`.

**This commit reduces compile time of Serde derives by 60% (takes less than half as long to compile)** as measured by building our test suite:

```console
$ git clone https://github.com/serde-rs/serde
$ cd serde/test_suite
$ cargo check --tests --features proc-macro2/nightly
$ rm -f ../target/debug/deps/libtest_*.rmeta
$ time cargo check --tests --features proc-macro2/nightly
Before: 20.8 seconds
After: 8.6 seconds
```

r? @alexcrichton
@bors
Copy link
Collaborator

bors commented Aug 16, 2018

☀️ Test successful - status-appveyor, status-travis
Approved by: dtolnay
Pushing b559042 to master...

@bors bors merged commit 69b9c23 into rust-lang:master Aug 16, 2018
@dtolnay dtolnay deleted the extend branch August 16, 2018 18:03
Copy link
Member Author

@dtolnay dtolnay left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perf looks clean, I see no regression from changing RcSlice to RcVec. perf comparison

@dtolnay dtolnay added T-libs-api Relevant to the library API team, which will review and decide on the PR/issue. and removed S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. labels Jan 14, 2025
@dtolnay dtolnay added the A-proc-macros Area: Procedural macros label Jan 14, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-proc-macros Area: Procedural macros T-libs-api Relevant to the library API team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants