Skip to content

Commit e62031e

Browse files
committed
rustdoc-search: better hashing, faster unification
The hash changes are based on some tests with `arti` and various specific queries, aimed at reducing the false positive rate. Sorting the query elements so that generics always come first is instead aimed at reducing the number of Map operations on mgens, assuming if the bloom filter does find a false positive, it'll be able to reject the row without having to track a mapping.
1 parent bada62b commit e62031e

File tree

1 file changed

+38
-10
lines changed

1 file changed

+38
-10
lines changed

src/librustdoc/html/static/js/search.js

+38-10
Original file line numberDiff line numberDiff line change
@@ -2268,8 +2268,27 @@ function initSearch(rawSearchIndex) {
22682268
);
22692269
}
22702270
} else if (parsedQuery.foundElems > 0) {
2271+
// Sort input and output so that generic type variables go first and
2272+
// types with generic parameters go last.
2273+
// That's because of the way unification is structured: it eats off
2274+
// the end, and hits a fast path if the last item is a simple atom.
2275+
const sortQ = (a, b) => {
2276+
const ag = a.generics.length === 0 && a.bindings.size === 0;
2277+
const bg = b.generics.length === 0 && b.bindings.size === 0;
2278+
if (ag !== bg) {
2279+
return ag - bg;
2280+
}
2281+
const ai = a.id > 0;
2282+
const bi = b.id > 0;
2283+
if (ai !== bi) {
2284+
return ai - bi;
2285+
}
2286+
return 0;
2287+
};
2288+
parsedQuery.elems.sort(sortQ);
2289+
parsedQuery.returned.sort(sortQ);
22712290
for (i = 0, nSearchWords = searchWords.length; i < nSearchWords; ++i) {
2272-
handleArgs(searchIndex[i], i, results_others);
2291+
handleArgs(searchIndex[i], searchIndex[i].id, results_others);
22732292
}
22742293
}
22752294
}
@@ -2841,15 +2860,25 @@ ${item.displayPath}<span class="${type}">${name}</span>\
28412860
if (input === typeNameIdOfArray || input === typeNameIdOfSlice) {
28422861
input = typeNameIdOfArrayOrSlice;
28432862
}
2844-
if (input !== null) {
2863+
const fxScram = k => {
28452864
// https://docs.rs/rustc-hash/1.1.0/src/rustc_hash/lib.rs.html#60
2846-
// Rotate is skipped because we're only doing one cycle anyway.
2847-
const h0 = Math.imul(input, 0x9e3779b9);
2848-
const h1 = Math.imul(479001599 ^ input, 0x9e3779b9);
2849-
const h2 = Math.imul(433494437 ^ input, 0x9e3779b9);
2850-
output[0] |= 1 << (h0 % 32);
2851-
output[1] |= 1 << (h1 % 32);
2852-
output[2] |= 1 << (h2 % 32);
2865+
return Math.imul((k << 5) | (k >> 27), 0x9e3779b9);
2866+
};
2867+
const murmurScram = k => {
2868+
// https://en.wikipedia.org/wiki/MurmurHash
2869+
k = Math.imul(k, 0xcc9e2d51);
2870+
return Math.imul((k << 15) | (k >> 17), 0x1b873593);
2871+
};
2872+
if (input !== null) {
2873+
const h0a = fxScram(input);
2874+
const h0b = murmurScram(input);
2875+
const h1a = fxScram(479001599 ^ input);
2876+
const h1b = murmurScram(479001599 ^ input);
2877+
const h2a = fxScram(433494437 ^ input);
2878+
const h2b = murmurScram(433494437 ^ input);
2879+
output[0] |= (1 << (h0a % 32)) | (1 << (h0b % 32));
2880+
output[1] |= (1 << (h1a % 32)) | (1 << (h1b % 32));
2881+
output[2] |= (1 << (h2a % 32)) | (1 << (h2b % 32));
28532882
fps.add(input);
28542883
}
28552884
for (const g of type.generics) {
@@ -2878,7 +2907,6 @@ ${item.displayPath}<span class="${type}">${name}</span>\
28782907
* This function might return 0!
28792908
*/
28802909
function compareTypeFingerprints(fullId, queryFingerprint) {
2881-
28822910
const fh0 = functionTypeFingerprint[fullId * 4];
28832911
const fh1 = functionTypeFingerprint[(fullId * 4) + 1];
28842912
const fh2 = functionTypeFingerprint[(fullId * 4) + 2];

0 commit comments

Comments
 (0)