From 2d5843d34ee99603ec0af0717a13eeca98d44c97 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 12 Dec 2019 13:28:07 +1100 Subject: [PATCH] [DO NOT LAND] Regress the `token-stream-stress` benchmark. I have a suspicion that there is a bug in rustc-perf or rust-timer causing the wrong revisions to be measured by CI. See #66405 and #67079 for more details. This commit deliberately causes a massive regression to the `token-stream-stress` benchmark. On my machine, the instruction count goes from 313M to 6084M, an 1843.4% regression. I want to see if a CI run replicates that. --- src/libsyntax/tokenstream.rs | 39 +++++++++--------------------------- 1 file changed, 9 insertions(+), 30 deletions(-) diff --git a/src/libsyntax/tokenstream.rs b/src/libsyntax/tokenstream.rs index 491b9a9ade47a..2be98e73c3c99 100644 --- a/src/libsyntax/tokenstream.rs +++ b/src/libsyntax/tokenstream.rs @@ -238,39 +238,18 @@ impl TokenStream { 0 => TokenStream::default(), 1 => streams.pop().unwrap(), _ => { - // We are going to extend the first stream in `streams` with - // the elements from the subsequent streams. This requires - // using `make_mut()` on the first stream, and in practice this - // doesn't cause cloning 99.9% of the time. - // - // One very common use case is when `streams` has two elements, - // where the first stream has any number of elements within - // (often 1, but sometimes many more) and the second stream has - // a single element within. - - // Determine how much the first stream will be extended. - // Needed to avoid quadratic blow up from on-the-fly - // reallocations (#57735). - let num_appends = streams.iter() - .skip(1) - .map(|ts| ts.len()) + // rust-lang/rust#57735: pre-allocate vector to avoid + // quadratic blow-up due to on-the-fly reallocations. + let tree_count = streams.iter() + .map(|ts| ts.0.len()) .sum(); - // Get the first stream. If it's `None`, create an empty - // stream. - let mut iter = streams.drain(..); - let mut first_stream_lrc = iter.next().unwrap().0; - - // Append the elements to the first stream, after reserving - // space for them. - let first_vec_mut = Lrc::make_mut(&mut first_stream_lrc); - first_vec_mut.reserve(num_appends); - for stream in iter { - first_vec_mut.extend(stream.0.iter().cloned()); - } + let mut vec = Vec::with_capacity(tree_count); - // Create the final `TokenStream`. - TokenStream(first_stream_lrc) + for stream in streams { + vec.extend(stream.0.iter().cloned()); + } + TokenStream::new(vec) } } }