Skip to content

Commit 17a8aff

Browse files
committed
Use SmallVec in TokenStreamBuilder.
This reduces by 12% the number of allocations done for a "clean incremental" of `webrender_api`, which reduces the instruction count by about 0.5%. It also reduces instruction counts by up to 1.4% across a range of rustc-perf benchmark runs.
1 parent 4c27fb1 commit 17a8aff

File tree

2 files changed

+10
-7
lines changed

2 files changed

+10
-7
lines changed

src/libsyntax/parse/attr.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use crate::parse::parser::{Parser, TokenType, PathStyle};
66
use crate::tokenstream::{TokenStream, TokenTree};
77

88
use log::debug;
9+
use smallvec::smallvec;
910

1011
#[derive(Debug)]
1112
enum InnerAttributeParsePolicy<'a> {
@@ -171,7 +172,7 @@ impl<'a> Parser<'a> {
171172
} else {
172173
self.parse_unsuffixed_lit()?.tokens()
173174
};
174-
TokenStream::from_streams(vec![eq.into(), tokens])
175+
TokenStream::from_streams(smallvec![eq.into(), tokens])
175176
} else {
176177
TokenStream::empty()
177178
};

src/libsyntax/tokenstream.rs

+8-6
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ use syntax_pos::{BytePos, Mark, Span, DUMMY_SP};
2424
use rustc_data_structures::static_assert;
2525
use rustc_data_structures::sync::Lrc;
2626
use serialize::{Decoder, Decodable, Encoder, Encodable};
27+
use smallvec::{SmallVec, smallvec};
2728

2829
use std::borrow::Cow;
2930
use std::{fmt, iter, mem};
@@ -224,7 +225,7 @@ impl From<Token> for TokenStream {
224225

225226
impl<T: Into<TokenStream>> iter::FromIterator<T> for TokenStream {
226227
fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
227-
TokenStream::from_streams(iter.into_iter().map(Into::into).collect::<Vec<_>>())
228+
TokenStream::from_streams(iter.into_iter().map(Into::into).collect::<SmallVec<_>>())
228229
}
229230
}
230231

@@ -256,7 +257,7 @@ impl TokenStream {
256257
}
257258
}
258259

259-
pub(crate) fn from_streams(mut streams: Vec<TokenStream>) -> TokenStream {
260+
pub(crate) fn from_streams(mut streams: SmallVec<[TokenStream; 2]>) -> TokenStream {
260261
match streams.len() {
261262
0 => TokenStream::empty(),
262263
1 => streams.pop().unwrap(),
@@ -393,12 +394,13 @@ impl TokenStream {
393394
}
394395
}
395396

397+
// 99.5%+ of the time we have 1 or 2 elements in this vector.
396398
#[derive(Clone)]
397-
pub struct TokenStreamBuilder(Vec<TokenStream>);
399+
pub struct TokenStreamBuilder(SmallVec<[TokenStream; 2]>);
398400

399401
impl TokenStreamBuilder {
400402
pub fn new() -> TokenStreamBuilder {
401-
TokenStreamBuilder(Vec::new())
403+
TokenStreamBuilder(SmallVec::new())
402404
}
403405

404406
pub fn push<T: Into<TokenStream>>(&mut self, stream: T) {
@@ -485,7 +487,7 @@ impl Cursor {
485487
}
486488
let index = self.index;
487489
let stream = mem::replace(&mut self.stream, TokenStream(None));
488-
*self = TokenStream::from_streams(vec![stream, new_stream]).into_trees();
490+
*self = TokenStream::from_streams(smallvec![stream, new_stream]).into_trees();
489491
self.index = index;
490492
}
491493

@@ -572,7 +574,7 @@ mod tests {
572574
let test_res = string_to_ts("foo::bar::baz");
573575
let test_fst = string_to_ts("foo::bar");
574576
let test_snd = string_to_ts("::baz");
575-
let eq_res = TokenStream::from_streams(vec![test_fst, test_snd]);
577+
let eq_res = TokenStream::from_streams(smallvec![test_fst, test_snd]);
576578
assert_eq!(test_res.trees().count(), 5);
577579
assert_eq!(eq_res.trees().count(), 5);
578580
assert_eq!(test_res.eq_unspanned(&eq_res), true);

0 commit comments

Comments
 (0)