Skip to content

Commit

Permalink
Rollup merge of rust-lang#71250 - GuillaumeGomez:use-json-instead-of-…
Browse files Browse the repository at this point in the history
…js, r=kinnison

Replace big JS dict with JSON parsing

Part of rust-lang#56545.

@ollie27 suggested that using JSON instead of a JS dict might be faster, so I decided to test it. And the results far exceeded whatever expectations I had...

I used https://github.com/adamgreig/stm32ral for my tests. If you want to build it locally:

```bash
$ cargo doc --features doc --open
```

But I strongly recommend to do it with this PR. Some numbers:

 * Loading a page with the JSON search-index: less than 1 second
 * Loading a page with the JS search-index: crashed after 30 seconds

I think the results are clear enough...

r? @ollie27

cc @rust-lang/rustdoc
  • Loading branch information
Dylan-DPC committed Apr 20, 2020
2 parents 4ca5fd2 + b4fb306 commit f208d24
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 5 deletions.
39 changes: 35 additions & 4 deletions src/librustdoc/html/render.rs
Original file line number Diff line number Diff line change
Expand Up @@ -789,6 +789,37 @@ themePicker.onblur = handleThemeButtonsBlur;
Ok((ret, krates))
}

fn collect_json(path: &Path, krate: &str) -> io::Result<(Vec<String>, Vec<String>)> {
let mut ret = Vec::new();
let mut krates = Vec::new();

if path.exists() {
for line in BufReader::new(File::open(path)?).lines() {
let line = line?;
if !line.starts_with("\"") {
continue;
}
if line.starts_with(&format!("\"{}\"", krate)) {
continue;
}
if line.ends_with(",\\") {
ret.push(line[..line.len() - 2].to_string());
} else {
// Ends with "\\" (it's the case for the last added crate line)
ret.push(line[..line.len() - 1].to_string());
}
krates.push(
line.split('"')
.filter(|s| !s.is_empty())
.next()
.map(|s| s.to_owned())
.unwrap_or_else(String::new),
);
}
}
Ok((ret, krates))
}

fn show_item(item: &IndexItem, krate: &str) -> String {
format!(
"{{'crate':'{}','ty':{},'name':'{}','desc':'{}','p':'{}'{}}}",
Expand Down Expand Up @@ -909,18 +940,18 @@ themePicker.onblur = handleThemeButtonsBlur;

// Update the search index
let dst = cx.dst.join(&format!("search-index{}.js", cx.shared.resource_suffix));
let (mut all_indexes, mut krates) = try_err!(collect(&dst, &krate.name, "searchIndex"), &dst);
let (mut all_indexes, mut krates) = try_err!(collect_json(&dst, &krate.name), &dst);
all_indexes.push(search_index);

// Sort the indexes by crate so the file will be generated identically even
// with rustdoc running in parallel.
all_indexes.sort();
{
let mut v = String::from("var searchIndex={};\n");
v.push_str(&all_indexes.join("\n"));
let mut v = String::from("var searchIndex = JSON.parse('{\\\n");
v.push_str(&all_indexes.join(",\\\n"));
// "addSearchOptions" has to be called first so the crate filtering can be set before the
// search might start (if it's set into the URL for example).
v.push_str("\naddSearchOptions(searchIndex);initSearch(searchIndex);");
v.push_str("\\\n}');\naddSearchOptions(searchIndex);initSearch(searchIndex);");
cx.shared.fs.write(&dst, &v)?;
}
if options.enable_index_page {
Expand Down
7 changes: 6 additions & 1 deletion src/librustdoc/html/render/cache.rs
Original file line number Diff line number Diff line change
Expand Up @@ -634,14 +634,19 @@ fn build_index(krate: &clean::Crate, cache: &mut Cache) -> String {

// Collect the index into a string
format!(
r#"searchIndex["{}"] = {};"#,
r#""{}":{}"#,
krate.name,
serde_json::to_string(&CrateData {
doc: crate_doc,
items: crate_items,
paths: crate_paths,
})
.expect("failed serde conversion")
// All these `replace` calls are because we have to go through JS string for JSON content.
.replace(r"\", r"\\")
.replace("'", r"\'")
// We need to escape double quotes for the JSON.
.replace("\\\"", "\\\\\"")
)
}

Expand Down

0 comments on commit f208d24

Please sign in to comment.