rustdoc: tweak the search index format
This essentially switches search-index.js from a "array of struct" to a "struct of array" format, like this: { "doc": "Crate documentation", "t": [ 1, 1, 2, 3, ... ], "n": [ "Something", "SomethingElse", "whatever", "do_stuff", ... ], "q": [ "a::b", "", "", "", ... ], "d": [ "A Struct That Does Something", "Another Struct", "a function", "another function", ... ], "i": [ 0, 0, 1, 1, ... ], "f": [ null, null, [], [], ... ], "p": ..., "a": ... } So `{ty: 1, name: "Something", path: "a::b", desc: "A Struct That Does Something", parent_idx: 0, search_type: null}` is the first item. This makes the uncompressed version smaller, but it really shows on the compressed version: notriddle:rust$ wc -c new-search-index1.52.0.js 2622427 new-search-index1.52.0.js notriddle:rust$ wc -c old-search-index1.52.0.js 2725046 old-search-index1.52.0.js notriddle:rust$ gzip new-search-index1.52.0.js notriddle:rust$ gzip old-search-index1.52.0.js notriddle:rust$ wc -c new-search-index1.52.0.js.gz 239385 new-search-index1.52.0.js.gz notriddle:rust$ wc -c old-search-index1.52.0.js.gz 296328 old-search-index1.52.0.js.gz notriddle:rust$ That's a 4% improvement on the uncompressed version (fewer `[]`), and 20% improvement after gzipping it, thanks to putting like-typed data next to each other. Any compression algorithm based on a sliding window will probably show this kind of improvement.
This commit is contained in:
parent
f98721f886
commit
3934dd1b3e
3 changed files with 74 additions and 42 deletions
|
@ -4,7 +4,7 @@ use std::path::Path;
|
||||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
||||||
use rustc_middle::ty::TyCtxt;
|
use rustc_middle::ty::TyCtxt;
|
||||||
use rustc_span::symbol::{sym, Symbol};
|
use rustc_span::symbol::{sym, Symbol};
|
||||||
use serde::Serialize;
|
use serde::ser::{Serialize, SerializeStruct, Serializer};
|
||||||
|
|
||||||
use crate::clean::types::{
|
use crate::clean::types::{
|
||||||
FnDecl, FnRetTy, GenericBound, Generics, GetDefId, Type, TypeKind, WherePredicate,
|
FnDecl, FnRetTy, GenericBound, Generics, GetDefId, Type, TypeKind, WherePredicate,
|
||||||
|
@ -133,21 +133,69 @@ crate fn build_index<'tcx>(krate: &clean::Crate, cache: &mut Cache, tcx: TyCtxt<
|
||||||
.map(|module| module.doc_value().map_or_else(String::new, |s| short_markdown_summary(&s)))
|
.map(|module| module.doc_value().map_or_else(String::new, |s| short_markdown_summary(&s)))
|
||||||
.unwrap_or_default();
|
.unwrap_or_default();
|
||||||
|
|
||||||
#[derive(Serialize)]
|
|
||||||
struct CrateData<'a> {
|
struct CrateData<'a> {
|
||||||
doc: String,
|
doc: String,
|
||||||
#[serde(rename = "i")]
|
|
||||||
items: Vec<&'a IndexItem>,
|
items: Vec<&'a IndexItem>,
|
||||||
#[serde(rename = "p")]
|
|
||||||
paths: Vec<(ItemType, String)>,
|
paths: Vec<(ItemType, String)>,
|
||||||
// The String is alias name and the vec is the list of the elements with this alias.
|
// The String is alias name and the vec is the list of the elements with this alias.
|
||||||
//
|
//
|
||||||
// To be noted: the `usize` elements are indexes to `items`.
|
// To be noted: the `usize` elements are indexes to `items`.
|
||||||
#[serde(rename = "a")]
|
|
||||||
#[serde(skip_serializing_if = "BTreeMap::is_empty")]
|
|
||||||
aliases: &'a BTreeMap<String, Vec<usize>>,
|
aliases: &'a BTreeMap<String, Vec<usize>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'a> Serialize for CrateData<'a> {
|
||||||
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||||
|
where
|
||||||
|
S: Serializer,
|
||||||
|
{
|
||||||
|
let has_aliases = !self.aliases.is_empty();
|
||||||
|
let mut crate_data =
|
||||||
|
serializer.serialize_struct("CrateData", if has_aliases { 9 } else { 8 })?;
|
||||||
|
crate_data.serialize_field("doc", &self.doc)?;
|
||||||
|
crate_data.serialize_field(
|
||||||
|
"t",
|
||||||
|
&self.items.iter().map(|item| &item.ty).collect::<Vec<_>>(),
|
||||||
|
)?;
|
||||||
|
crate_data.serialize_field(
|
||||||
|
"n",
|
||||||
|
&self.items.iter().map(|item| &item.name).collect::<Vec<_>>(),
|
||||||
|
)?;
|
||||||
|
crate_data.serialize_field(
|
||||||
|
"q",
|
||||||
|
&self.items.iter().map(|item| &item.path).collect::<Vec<_>>(),
|
||||||
|
)?;
|
||||||
|
crate_data.serialize_field(
|
||||||
|
"d",
|
||||||
|
&self.items.iter().map(|item| &item.desc).collect::<Vec<_>>(),
|
||||||
|
)?;
|
||||||
|
crate_data.serialize_field(
|
||||||
|
"i",
|
||||||
|
&self
|
||||||
|
.items
|
||||||
|
.iter()
|
||||||
|
.map(|item| {
|
||||||
|
assert_eq!(
|
||||||
|
item.parent.is_some(),
|
||||||
|
item.parent_idx.is_some(),
|
||||||
|
"`{}` is missing idx",
|
||||||
|
item.name
|
||||||
|
);
|
||||||
|
item.parent_idx.map(|x| x + 1).unwrap_or(0)
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>(),
|
||||||
|
)?;
|
||||||
|
crate_data.serialize_field(
|
||||||
|
"f",
|
||||||
|
&self.items.iter().map(|item| &item.search_type).collect::<Vec<_>>(),
|
||||||
|
)?;
|
||||||
|
crate_data.serialize_field("p", &self.paths)?;
|
||||||
|
if has_aliases {
|
||||||
|
crate_data.serialize_field("a", &self.aliases)?;
|
||||||
|
}
|
||||||
|
crate_data.end()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Collect the index into a string
|
// Collect the index into a string
|
||||||
format!(
|
format!(
|
||||||
r#""{}":{}"#,
|
r#""{}":{}"#,
|
||||||
|
|
|
@ -166,23 +166,6 @@ crate struct IndexItem {
|
||||||
crate search_type: Option<IndexItemFunctionType>,
|
crate search_type: Option<IndexItemFunctionType>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Serialize for IndexItem {
|
|
||||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
|
||||||
where
|
|
||||||
S: Serializer,
|
|
||||||
{
|
|
||||||
assert_eq!(
|
|
||||||
self.parent.is_some(),
|
|
||||||
self.parent_idx.is_some(),
|
|
||||||
"`{}` is missing idx",
|
|
||||||
self.name
|
|
||||||
);
|
|
||||||
|
|
||||||
(self.ty, &self.name, &self.path, &self.desc, self.parent_idx, &self.search_type)
|
|
||||||
.serialize(serializer)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A type used for the search index.
|
/// A type used for the search index.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
crate struct RenderType {
|
crate struct RenderType {
|
||||||
|
|
|
@ -1847,13 +1847,18 @@ function defocusSearchBar() {
|
||||||
});
|
});
|
||||||
currentIndex += 1;
|
currentIndex += 1;
|
||||||
|
|
||||||
// an array of [(Number) item type,
|
// an array of (Number) item types
|
||||||
// (String) name,
|
var itemTypes = rawSearchIndex[crate].t;
|
||||||
// (String) full path or empty string for previous path,
|
// an array of (String) item names
|
||||||
// (String) description,
|
var itemNames = rawSearchIndex[crate].n;
|
||||||
// (Number | null) the parent path index to `paths`]
|
// an array of (String) full paths (or empty string for previous path)
|
||||||
// (Object | null) the type of the function (if any)
|
var itemPaths = rawSearchIndex[crate].q;
|
||||||
var items = rawSearchIndex[crate].i;
|
// an array of (String) descriptions
|
||||||
|
var itemDescs = rawSearchIndex[crate].d;
|
||||||
|
// an array of (Number) the parent path index + 1 to `paths`, or 0 if none
|
||||||
|
var itemParentIdxs = rawSearchIndex[crate].i;
|
||||||
|
// an array of (Object | null) the type of the function, if any
|
||||||
|
var itemFunctionSearchTypes = rawSearchIndex[crate].f;
|
||||||
// an array of [(Number) item type,
|
// an array of [(Number) item type,
|
||||||
// (String) name]
|
// (String) name]
|
||||||
var paths = rawSearchIndex[crate].p;
|
var paths = rawSearchIndex[crate].p;
|
||||||
|
@ -1867,28 +1872,24 @@ function defocusSearchBar() {
|
||||||
paths[i] = {ty: paths[i][0], name: paths[i][1]};
|
paths[i] = {ty: paths[i][0], name: paths[i][1]};
|
||||||
}
|
}
|
||||||
|
|
||||||
// convert `items` into an object form, and construct word indices.
|
// convert `item*` into an object form, and construct word indices.
|
||||||
//
|
//
|
||||||
// before any analysis is performed lets gather the search terms to
|
// before any analysis is performed lets gather the search terms to
|
||||||
// search against apart from the rest of the data. This is a quick
|
// search against apart from the rest of the data. This is a quick
|
||||||
// operation that is cached for the life of the page state so that
|
// operation that is cached for the life of the page state so that
|
||||||
// all other search operations have access to this cached data for
|
// all other search operations have access to this cached data for
|
||||||
// faster analysis operations
|
// faster analysis operations
|
||||||
len = items.length;
|
len = itemTypes.length;
|
||||||
var lastPath = "";
|
var lastPath = "";
|
||||||
for (i = 0; i < len; ++i) {
|
for (i = 0; i < len; ++i) {
|
||||||
var rawRow = items[i];
|
|
||||||
if (!rawRow[2]) {
|
|
||||||
rawRow[2] = lastPath;
|
|
||||||
}
|
|
||||||
var row = {
|
var row = {
|
||||||
crate: crate,
|
crate: crate,
|
||||||
ty: rawRow[0],
|
ty: itemTypes[i],
|
||||||
name: rawRow[1],
|
name: itemNames[i],
|
||||||
path: rawRow[2],
|
path: itemPaths[i] ? itemPaths[i] : lastPath,
|
||||||
desc: rawRow[3],
|
desc: itemDescs[i],
|
||||||
parent: paths[rawRow[4]],
|
parent: itemParentIdxs[i] > 0 ? paths[itemParentIdxs[i] - 1] : undefined,
|
||||||
type: rawRow[5],
|
type: itemFunctionSearchTypes[i],
|
||||||
};
|
};
|
||||||
searchIndex.push(row);
|
searchIndex.push(row);
|
||||||
if (typeof row.name === "string") {
|
if (typeof row.name === "string") {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue