Skip to content

Commit 225140e

Browse files
committed
Optimize local linkchecker program
I noticed on a [recent build][1] that the linkchecker stage of CI took a whopping 15 minutes of CI time for something that should be near instantaneous. Some local profiling showed some very hot functions and clones which were pretty easy to remove, and now instead of running in minutes locally it runs in seconds. [1]: https://ci.appveyor.com/project/rust-lang/rust/build/job/kptifw1kb1nm4xuu
1 parent 3e90a12 commit 225140e

File tree

1 file changed

+19
-19
lines changed

1 file changed

+19
-19
lines changed

src/tools/linkchecker/main.rs

+19-19
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,12 @@
2424
//! A few whitelisted exceptions are allowed as there's known bugs in rustdoc,
2525
//! but this should catch the majority of "broken link" cases.
2626
27+
use std::collections::hash_map::Entry;
28+
use std::collections::{HashMap, HashSet};
2729
use std::env;
28-
use std::fs::File;
29-
use std::io::prelude::*;
30+
use std::fs;
3031
use std::path::{Path, PathBuf, Component};
31-
use std::collections::{HashMap, HashSet};
32-
use std::collections::hash_map::Entry;
32+
use std::rc::Rc;
3333

3434
use Redirect::*;
3535

@@ -63,7 +63,7 @@ enum Redirect {
6363
}
6464

6565
struct FileEntry {
66-
source: String,
66+
source: Rc<String>,
6767
ids: HashSet<String>,
6868
}
6969

@@ -113,7 +113,7 @@ fn walk(cache: &mut Cache, root: &Path, dir: &Path, errors: &mut bool) {
113113
let entry = cache.get_mut(&pretty_path).unwrap();
114114
// we don't need the source anymore,
115115
// so drop to reduce memory-usage
116-
entry.source = String::new();
116+
entry.source = Rc::new(String::new());
117117
}
118118
}
119119
}
@@ -287,24 +287,24 @@ fn load_file(cache: &mut Cache,
287287
root: &Path,
288288
file: &Path,
289289
redirect: Redirect)
290-
-> Result<(PathBuf, String), LoadError> {
291-
let mut contents = String::new();
290+
-> Result<(PathBuf, Rc<String>), LoadError> {
292291
let pretty_file = PathBuf::from(file.strip_prefix(root).unwrap_or(&file));
293292

294-
let maybe_redirect = match cache.entry(pretty_file.clone()) {
293+
let (maybe_redirect, contents) = match cache.entry(pretty_file.clone()) {
295294
Entry::Occupied(entry) => {
296-
contents = entry.get().source.clone();
297-
None
295+
(None, entry.get().source.clone())
298296
}
299297
Entry::Vacant(entry) => {
300-
let mut fp = File::open(file).map_err(|err| {
301-
if let FromRedirect(true) = redirect {
302-
LoadError::BrokenRedirect(file.to_path_buf(), err)
303-
} else {
304-
LoadError::IOError(err)
298+
let contents = match fs::read_to_string(file) {
299+
Ok(s) => Rc::new(s),
300+
Err(err) => {
301+
return Err(if let FromRedirect(true) = redirect {
302+
LoadError::BrokenRedirect(file.to_path_buf(), err)
303+
} else {
304+
LoadError::IOError(err)
305+
})
305306
}
306-
})?;
307-
fp.read_to_string(&mut contents).map_err(|err| LoadError::IOError(err))?;
307+
};
308308

309309
let maybe = maybe_redirect(&contents);
310310
if maybe.is_some() {
@@ -317,7 +317,7 @@ fn load_file(cache: &mut Cache,
317317
ids: HashSet::new(),
318318
});
319319
}
320-
maybe
320+
(maybe, contents)
321321
}
322322
};
323323
match maybe_redirect.map(|url| file.parent().unwrap().join(url)) {

0 commit comments

Comments
 (0)