about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2017-10-15 17:48:12 +0000
committerbors <bors@rust-lang.org>2017-10-15 17:48:12 +0000
commitc4f489af912bea9ca9f0fa0378d7c0acacf6c59e (patch)
treef13285a475cde29d2f97d75864aa7359c36a2562
parent2689fd2402590961dae32f35369a8685c89022fb (diff)
parent2c9d452a295c192f3e4762225fc4f4feef6f769c (diff)
downloadrust-c4f489af912bea9ca9f0fa0378d7c0acacf6c59e.tar.gz
rust-c4f489af912bea9ca9f0fa0378d7c0acacf6c59e.zip
Auto merge of #44613 - QuietMisdreavus:rustdoc-perf, r=michaelwoerister
some low-hanging rustdoc optimizations

There were a few discussions earlier today in #rust-internals about the syscall usage and overall performance of rustdoc. This PR is intended to pick some low-hanging fruit and try to rein in some of the performance issues of rustdoc.
-rw-r--r--src/librustdoc/html/render.rs27
1 files changed, 22 insertions, 5 deletions
diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs
index 967a19e0e96..3c789cb3a15 100644
--- a/src/librustdoc/html/render.rs
+++ b/src/librustdoc/html/render.rs
@@ -125,6 +125,21 @@ pub struct SharedContext {
     /// Warnings for the user if rendering would differ using different markdown
     /// parsers.
     pub markdown_warnings: RefCell<Vec<(Span, String, Vec<html_diff::Difference>)>>,
+    /// The directories that have already been created in this doc run. Used to reduce the number
+    /// of spurious `create_dir_all` calls.
+    pub created_dirs: RefCell<FxHashSet<PathBuf>>,
+}
+
+impl SharedContext {
+    fn ensure_dir(&self, dst: &Path) -> io::Result<()> {
+        let mut dirs = self.created_dirs.borrow_mut();
+        if !dirs.contains(dst) {
+            fs::create_dir_all(dst)?;
+            dirs.insert(dst.to_path_buf());
+        }
+
+        Ok(())
+    }
 }
 
 /// Indicates where an external crate can be found.
@@ -463,6 +478,7 @@ pub fn run(mut krate: clean::Crate,
         },
         css_file_extension: css_file_extension.clone(),
         markdown_warnings: RefCell::new(vec![]),
+        created_dirs: RefCell::new(FxHashSet()),
     };
 
     // If user passed in `--playground-url` arg, we fill in crate name here
@@ -794,7 +810,6 @@ fn write_shared(cx: &Context,
     // Write out the shared files. Note that these are shared among all rustdoc
     // docs placed in the output directory, so this needs to be a synchronized
     // operation with respect to all other rustdocs running around.
-    try_err!(fs::create_dir_all(&cx.dst), &cx.dst);
     let _lock = flock::Lock::panicking_new(&cx.dst.join(".lock"), true, true, true);
 
     // Add all the static files. These may already exist, but we just
@@ -1518,8 +1533,8 @@ impl Context {
                 this.render_item(&mut buf, &item, false).unwrap();
                 // buf will be empty if the module is stripped and there is no redirect for it
                 if !buf.is_empty() {
+                    try_err!(this.shared.ensure_dir(&this.dst), &this.dst);
                     let joint_dst = this.dst.join("index.html");
-                    try_err!(fs::create_dir_all(&this.dst), &this.dst);
                     let mut dst = try_err!(File::create(&joint_dst), &joint_dst);
                     try_err!(dst.write_all(&buf), &joint_dst);
                 }
@@ -1553,8 +1568,8 @@ impl Context {
                 let name = item.name.as_ref().unwrap();
                 let item_type = item.type_();
                 let file_name = &item_path(item_type, name);
+                try_err!(self.shared.ensure_dir(&self.dst), &self.dst);
                 let joint_dst = self.dst.join(file_name);
-                try_err!(fs::create_dir_all(&self.dst), &self.dst);
                 let mut dst = try_err!(File::create(&joint_dst), &joint_dst);
                 try_err!(dst.write_all(&buf), &joint_dst);
 
@@ -1562,9 +1577,10 @@ impl Context {
                 // URL for the page.
                 let redir_name = format!("{}.{}.html", name, item_type.name_space());
                 let redir_dst = self.dst.join(redir_name);
-                if let Ok(mut redirect_out) = OpenOptions::new().create_new(true)
+                if let Ok(redirect_out) = OpenOptions::new().create_new(true)
                                                                 .write(true)
                                                                 .open(&redir_dst) {
+                    let mut redirect_out = BufWriter::new(redirect_out);
                     try_err!(layout::redirect(&mut redirect_out, file_name), &redir_dst);
                 }
 
@@ -1574,7 +1590,8 @@ impl Context {
                 if item_type == ItemType::Macro {
                     let redir_name = format!("{}.{}!.html", item_type, name);
                     let redir_dst = self.dst.join(redir_name);
-                    let mut redirect_out = try_err!(File::create(&redir_dst), &redir_dst);
+                    let redirect_out = try_err!(File::create(&redir_dst), &redir_dst);
+                    let mut redirect_out = BufWriter::new(redirect_out);
                     try_err!(layout::redirect(&mut redirect_out, file_name), &redir_dst);
                 }
             }