Skip to content

Commit 2f06ac0

Browse files
authored
Rollup merge of #71250 - GuillaumeGomez:use-json-instead-of-js, r=kinnison
Replace big JS dict with JSON parsing Part of #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
2 parents 8ce3f84 + b4fb306 commit 2f06ac0

File tree

2 files changed

+41
-5
lines changed

2 files changed

+41
-5
lines changed

src/librustdoc/html/render.rs

+35-4
Original file line numberDiff line numberDiff line change
@@ -789,6 +789,37 @@ themePicker.onblur = handleThemeButtonsBlur;
789789
Ok((ret, krates))
790790
}
791791

792+
fn collect_json(path: &Path, krate: &str) -> io::Result<(Vec<String>, Vec<String>)> {
793+
let mut ret = Vec::new();
794+
let mut krates = Vec::new();
795+
796+
if path.exists() {
797+
for line in BufReader::new(File::open(path)?).lines() {
798+
let line = line?;
799+
if !line.starts_with("\"") {
800+
continue;
801+
}
802+
if line.starts_with(&format!("\"{}\"", krate)) {
803+
continue;
804+
}
805+
if line.ends_with(",\\") {
806+
ret.push(line[..line.len() - 2].to_string());
807+
} else {
808+
// Ends with "\\" (it's the case for the last added crate line)
809+
ret.push(line[..line.len() - 1].to_string());
810+
}
811+
krates.push(
812+
line.split('"')
813+
.filter(|s| !s.is_empty())
814+
.next()
815+
.map(|s| s.to_owned())
816+
.unwrap_or_else(String::new),
817+
);
818+
}
819+
}
820+
Ok((ret, krates))
821+
}
822+
792823
fn show_item(item: &IndexItem, krate: &str) -> String {
793824
format!(
794825
"{{'crate':'{}','ty':{},'name':'{}','desc':'{}','p':'{}'{}}}",
@@ -909,18 +940,18 @@ themePicker.onblur = handleThemeButtonsBlur;
909940

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

915946
// Sort the indexes by crate so the file will be generated identically even
916947
// with rustdoc running in parallel.
917948
all_indexes.sort();
918949
{
919-
let mut v = String::from("var searchIndex={};\n");
920-
v.push_str(&all_indexes.join("\n"));
950+
let mut v = String::from("var searchIndex = JSON.parse('{\\\n");
951+
v.push_str(&all_indexes.join(",\\\n"));
921952
// "addSearchOptions" has to be called first so the crate filtering can be set before the
922953
// search might start (if it's set into the URL for example).
923-
v.push_str("\naddSearchOptions(searchIndex);initSearch(searchIndex);");
954+
v.push_str("\\\n}');\naddSearchOptions(searchIndex);initSearch(searchIndex);");
924955
cx.shared.fs.write(&dst, &v)?;
925956
}
926957
if options.enable_index_page {

src/librustdoc/html/render/cache.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -634,14 +634,19 @@ fn build_index(krate: &clean::Crate, cache: &mut Cache) -> String {
634634

635635
// Collect the index into a string
636636
format!(
637-
r#"searchIndex["{}"] = {};"#,
637+
r#""{}":{}"#,
638638
krate.name,
639639
serde_json::to_string(&CrateData {
640640
doc: crate_doc,
641641
items: crate_items,
642642
paths: crate_paths,
643643
})
644644
.expect("failed serde conversion")
645+
// All these `replace` calls are because we have to go through JS string for JSON content.
646+
.replace(r"\", r"\\")
647+
.replace("'", r"\'")
648+
// We need to escape double quotes for the JSON.
649+
.replace("\\\"", "\\\\\"")
645650
)
646651
}
647652

0 commit comments

Comments
 (0)