-
Notifications
You must be signed in to change notification settings - Fork 13.4k
rustdoc search: prefer stable items in search results #141658
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1463,6 +1463,11 @@ class DocSearch { | |
* @type {Map<String, RoaringBitmap>} | ||
*/ | ||
this.searchIndexEmptyDesc = new Map(); | ||
/** | ||
* @type {Map<String, RoaringBitmap>} | ||
*/ | ||
this.searchIndexUnstable = new Map(); | ||
|
||
/** | ||
* @type {Uint32Array} | ||
*/ | ||
|
@@ -2048,9 +2053,10 @@ class DocSearch { | |
}; | ||
const descShardList = [descShard]; | ||
|
||
// Deprecated items and items with no description | ||
// Deprecated and unstable items and items with no description | ||
this.searchIndexDeprecated.set(crate, new RoaringBitmap(crateCorpus.c)); | ||
this.searchIndexEmptyDesc.set(crate, new RoaringBitmap(crateCorpus.e)); | ||
this.searchIndexUnstable.set(crate, new RoaringBitmap(crateCorpus.u)); | ||
let descIndex = 0; | ||
|
||
/** | ||
|
@@ -3284,6 +3290,19 @@ class DocSearch { | |
return a - b; | ||
} | ||
|
||
// sort unstable items later | ||
a = Number( | ||
// @ts-expect-error | ||
this.searchIndexUnstable.get(aaa.item.crate).contains(aaa.item.bitIndex), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Instead of retrieving this information every time, why not storing this information in the related item when we build the search index? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yeah, you're right, we should keep linear scans out of inner loops if possible. if we have a binary search impl, or if we ever pull one in in the future, we could actually use that to speed up the unpacking time for the search index (since we can pre-sort them when generating the index), though it's probably not worth embedding a binary search impl for something that only speeds up the standard libraries. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah, right, I copied this from the implementation of deprecated items sorting, so if we want to change one, we should probably change all of them (especially because those ones will be applicable to all crates). Also, we have RoaringBitmap, so it's not a linear scan, actually. I'm not sure what the memory impact of having 3 more boolean fields on each row is (especially when one of those is going to be unused in every non-sysroot crate), so I would kinda wanna do some degree of perf testing to see if this is worth it. One thing we could do actually would be to add this data during TL;DR it's actually not obvious what the most performant solution would be, so I'd rather stick with what the code is already doing and then maybe make a followup PR focused on performance. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Adding this data when we build the search index seems like the way to go. As for performance checking, @notriddle wrote a tool for it (which you can find here if I'm not wrong). There are multiple ways of limiting the impact on performance. Another idea I had would be to put the new comparison in a function which would be created during search index creation: if we don't have any stability information, then the function is empty. Anyway, it'll likely impact performance of all crates using rustdoc (both std/core/alloc and the others without stability info) so I'd really prefer to ensure what the impact is before approving it. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Is a dynamic function call faster than a searching an empty bitmap? I'm trying to run the perf tool, but i'm having a bit of trouble making a full custom toolchain, probably due to bootstrap settings. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I got it "working" and I think it's a bit out of date:
|
||
); | ||
b = Number( | ||
// @ts-expect-error | ||
this.searchIndexUnstable.get(bbb.item.crate).contains(bbb.item.bitIndex), | ||
); | ||
if (a !== b) { | ||
return a - b; | ||
} | ||
|
||
// sort by crate (current crate comes first) | ||
a = Number(aaa.item.crate !== preferredCrate); | ||
b = Number(bbb.item.crate !== preferredCrate); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
const EXPECTED = [ | ||
{ | ||
'query': 'foo', | ||
'others': [ | ||
{"path": "sort_stability::old", "name": "foo"}, | ||
{"path": "sort_stability::new", "name": "foo"}, | ||
], | ||
}, | ||
]; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
#![feature(staged_api)] | ||
#![stable(feature = "foo_lib", since = "1.0.0")] | ||
|
||
#[stable(feature = "old_foo", since = "1.0.1")] | ||
pub mod old { | ||
/// Old, stable foo | ||
#[stable(feature = "old_foo", since = "1.0.1")] | ||
pub fn foo() {} | ||
} | ||
|
||
#[unstable(feature = "new_foo", issue = "none")] | ||
pub mod new { | ||
/// New, unstable foo | ||
#[unstable(feature = "new_foo", issue = "none")] | ||
pub fn foo() {} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could we add this field only if
unstable
is not empty?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we could, although i'm pretty sure it would make most doc bundles bigger, as the logic for handling the undef field would be more than 6 bytes, even when minified (i believe this is why we don't omit other fields either, even tho many crates have no reexports or aliases)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point, I'll keep that in a corner of my memory until I have some idea on how to make it better.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we can get part of the way there by noticing js truthiness rules are just sane enough for this case, the only falsy string value is the empty string, so we can do
| ""
to cleanse the undef. we're still using a few chars for the field access though, so i think in order to make this profitable we have to put this in a loop and apply it to multiple fields. unfortunately our fields are not homogeneous, so we'll need a different default value for different fields, meaning we'd be barely breaking even in the average case.honestly if we want to make the search index smaller, we're much better off chasing an improvement that scales, like delta compressing the row ids, instead of trying to save a single digit number of bytes.