Skip to content

Commit

Permalink
Optimize long-linker-command-line test
Browse files Browse the repository at this point in the history
Replace O(n^3) text matching with inexpensive hash set lookups.

On my machine this reduces the total runtime of complete
run-make-fulldeps suite from roughly 75 seconds to 45 seconds.
  • Loading branch information
tmiasko committed Oct 29, 2019
1 parent d3d28a4 commit afbb89e
Showing 1 changed file with 48 additions and 29 deletions.
77 changes: 48 additions & 29 deletions src/test/run-make-fulldeps/long-linker-command-lines/foo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,43 @@
// Eventually we should see an argument that looks like `@` as we switch from
// passing literal arguments to passing everything in the file.

use std::collections::HashSet;
use std::env;
use std::fs::{self, File};
use std::io::{BufWriter, Write, Read};
use std::path::PathBuf;
use std::io::{BufWriter, Write};
use std::path::{Path, PathBuf};
use std::process::Command;

fn write_test_case(file: &Path, n: usize) -> HashSet<String> {
let mut libs = HashSet::new();
let mut f = BufWriter::new(File::create(&file).unwrap());
let mut prefix = String::new();
for _ in 0..n {
prefix.push_str("foo");
}
for i in 0..n {
writeln!(f, "#[link(name = \"{}{}\")]", prefix, i).unwrap();
libs.insert(format!("{}{}", prefix, i));
}
writeln!(f, "extern {{}}\nfn main() {{}}").unwrap();
f.into_inner().unwrap();

libs
}

fn read_linker_args(path: &Path) -> String {
let contents = fs::read(path).unwrap();
if cfg!(target_env = "msvc") {
let mut i = contents.chunks(2).map(|c| {
c[0] as u16 | ((c[1] as u16) << 8)
});
assert_eq!(i.next(), Some(0xfeff), "Expected UTF-16 BOM");
String::from_utf16(&i.collect::<Vec<u16>>()).unwrap()
} else {
String::from_utf8(contents).unwrap()
}
}

fn main() {
let tmpdir = PathBuf::from(env::var_os("TMPDIR").unwrap());
let ok = tmpdir.join("ok");
Expand All @@ -29,16 +60,7 @@ fn main() {
for i in (1..).map(|i| i * 100) {
println!("attempt: {}", i);
let file = tmpdir.join("bar.rs");
let mut f = BufWriter::new(File::create(&file).unwrap());
let mut lib_name = String::new();
for _ in 0..i {
lib_name.push_str("foo");
}
for j in 0..i {
writeln!(f, "#[link(name = \"{}{}\")]", lib_name, j).unwrap();
}
writeln!(f, "extern {{}}\nfn main() {{}}").unwrap();
f.into_inner().unwrap();
let mut expected_libs = write_test_case(&file, i);

drop(fs::remove_file(&ok));
let output = Command::new(&rustc)
Expand Down Expand Up @@ -67,25 +89,22 @@ fn main() {
continue
}

let mut contents = Vec::new();
File::open(&ok).unwrap().read_to_end(&mut contents).unwrap();

for j in 0..i {
let exp = format!("{}{}", lib_name, j);
let exp = if cfg!(target_env = "msvc") {
let mut out = Vec::with_capacity(exp.len() * 2);
for c in exp.encode_utf16() {
// encode in little endian
out.push(c as u8);
out.push((c >> 8) as u8);
}
out
} else {
exp.into_bytes()
};
assert!(contents.windows(exp.len()).any(|w| w == &exp[..]));
for mut arg in read_linker_args(&ok).lines() {
if arg.starts_with("-l") {
arg = &arg["-l".len()..];
}
if arg.ends_with(".lib") {
arg = &arg[..arg.len() - ".lib".len()];
}
expected_libs.remove(arg);
}

assert!(
expected_libs.is_empty(),
"expected but missing libraries: {:#?}",
expected_libs,
);

break
}
}

0 comments on commit afbb89e

Please sign in to comment.