Skip to content
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

rustdoc: Separate filter-empty-string out into its own function #83717

Merged
merged 2 commits into from
Apr 5, 2021

Conversation

notriddle
Copy link
Contributor

No description provided.

@rust-highfive
Copy link
Collaborator

Some changes occurred in HTML/CSS/JS.

cc @GuillaumeGomez

@rust-highfive
Copy link
Collaborator

r? @GuillaumeGomez

(rust-highfive has picked a reviewer for you, use r? to override)

@rust-highfive rust-highfive added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Mar 31, 2021
@GuillaumeGomez
Copy link
Member

When comparing performance between the two, the "manual" filter is much faster. Results say that your proposition is 17.61% slower. I tested it on jsbench.me with the following array:

var x = ["a", "hbqsdq", "hbqsdq", "hbqsdq", "hbqsdq", "hbqsdq", "hbqsdq", "hbqsdq","hbqsdq","hbqsdq","hbqsdq","hbqsdq","hbqsdq","hbqsdq","hbqsdq","hbqsdq","hbqsdq","hbqsdq","hbqsdq","hbqsdq","","a", "hbqsdq", "hbqsdq", "hbqsdq", "hbqsdq", "hbqsdq", "hbqsdq", "hbqsdq","hbqsdq","hbqsdq","hbqsdq","hbqsdq","hbqsdq","hbqsdq","hbqsdq","hbqsdq","hbqsdq","hbqsdq","hbqsdq","hbqsdq","","a", "hbqsdq", "hbqsdq", "hbqsdq", "hbqsdq", "hbqsdq", "hbqsdq", "hbqsdq","hbqsdq","hbqsdq","hbqsdq","hbqsdq","hbqsdq","hbqsdq","hbqsdq","hbqsdq","hbqsdq","hbqsdq","hbqsdq","hbqsdq","","a", "hbqsdq", "hbqsdq", "hbqsdq", "hbqsdq", "hbqsdq", "hbqsdq", "hbqsdq","hbqsdq","hbqsdq","hbqsdq","hbqsdq","hbqsdq","hbqsdq","hbqsdq","hbqsdq","hbqsdq","hbqsdq","hbqsdq","hbqsdq","","a", "hbqsdq", "hbqsdq", "hbqsdq", "hbqsdq", "hbqsdq", "hbqsdq", "hbqsdq","hbqsdq","hbqsdq","hbqsdq","hbqsdq","hbqsdq","hbqsdq","hbqsdq","hbqsdq","hbqsdq","hbqsdq","hbqsdq","hbqsdq","","a", "hbqsdq", "hbqsdq", "hbqsdq", "hbqsdq", "hbqsdq", "hbqsdq", "hbqsdq","hbqsdq","hbqsdq","hbqsdq","hbqsdq","hbqsdq","hbqsdq","hbqsdq","hbqsdq","hbqsdq","hbqsdq","hbqsdq","hbqsdq","","a", "hbqsdq", "hbqsdq", "hbqsdq", "hbqsdq", "hbqsdq", "hbqsdq", "hbqsdq","hbqsdq","hbqsdq","hbqsdq","hbqsdq","hbqsdq","hbqsdq","hbqsdq","hbqsdq","hbqsdq","hbqsdq","hbqsdq","hbqsdq","","a", "hbqsdq", "hbqsdq", "hbqsdq", "hbqsdq", "hbqsdq", "hbqsdq", "hbqsdq","hbqsdq","hbqsdq","hbqsdq","hbqsdq","hbqsdq","hbqsdq","hbqsdq","hbqsdq","hbqsdq","hbqsdq","hbqsdq","hbqsdq",""];

Then the two following codes:

x = x.filter(function(f) { return f !== ""; });

and:

for (var i = 0, len = x.length; i < len; ++i) {
    if (x[i] === "") {
        x.splice(i, 1);
        i -= 1;
    }
}

If you confirm the result, I think it can be closed. However, could you add a comment saying that the current code is faster please?

@notriddle
Copy link
Contributor Author

Immediately below the code that I changed, it loops through every item in the search index, and then runs checkPath on it. checkPath itself loops over every segment of that path. This makes the algorithmic complexity of that loop O(nSearchWords * paths.length). The only case I can think of where it makes sense to sacrifice readability of this search query parsing code in favor of performance, since it's O(paths.length) either way, is if you have a small crate, and apply a large search query to it.

Honestly, I wasn't really trying to make this code faster, because I assume that nSearchWords will be much, much larger than paths.length. I just thought this code was more readable (it's certainly shorter).

@GuillaumeGomez
Copy link
Member

GuillaumeGomez commented Apr 1, 2021

Performance in the search is important. But you can move the code into a filter function instead if you prefer (but still not use the official filter function, I think it's the callback which slows things down...). A bit of readability there would definitely be appreciated.

@notriddle
Copy link
Contributor Author

@GuillaumeGomez

Okay, I've separated the empty string filter out into its own function, and also used a version that's about 10% faster according to jsbench.me (I designed it thinking that Array.prototype.splice had to renumber everything, so it would be better to only call it once).

@notriddle notriddle changed the title rustdoc: use Array.prototype.filter instead of open-coding it rustdoc: Separate filter-empty-string out into its own function Apr 1, 2021
@rust-log-analyzer

This comment has been minimized.

@GuillaumeGomez
Copy link
Member

About the CI failure, it's because you need to update the rustdoc-js script by adding the name of your function here.

@GuillaumeGomez
Copy link
Member

Looks all good to me now. Thanks a lot for both performance and code readability improvements!

@notriddle
Copy link
Contributor Author

Okay, I fixed the test case, and also did further tweaks to the function... there's an annoying amount of engine-specific behaviour here.

Given these two functions:

function removeEmptyStringsFromArray_A(x) {
    for (var i = 0, len = x.length; i < len; ++i) {
        if (x[i] === "") {
            x.splice(i, 1);
            i -= 1;
        }
    }
}
function removeEmptyStringsFromArray_B(x) {
    for (var i = x.length - 1, j = x.length - 1; j >= 0; j -= 1) {
        if (x[j] !== "") {
            x[i] = x[j];
            i -= 1;
        }
    }
    x.splice(0, i + 1);
}

In Firefox, version A is reported to be 43% slower than version B, but in Chromium, version B is 12.5% slower than version A, using your original test data.

What's really annoying is that there's never a point where B becomes faster. I would've expected a splice nested inside of a loop to have O(n2) runtime, since it ought to renumber the array, but given the apparent worst-case of an array containing nothing but empty strings, both engines perform better with version A. Does anyone have any idea what's going on?

@GuillaumeGomez
Copy link
Member

Might need to ask to the people who actually write the JS engine at this point... If you know any?

@GuillaumeGomez GuillaumeGomez added the T-rustdoc Relevant to the rustdoc team, which will review and decide on the PR/issue. label Apr 4, 2021
@GuillaumeGomez
Copy link
Member

For now, let's go forward with this already.

@bors: r+ rollup

@bors
Copy link
Contributor

bors commented Apr 4, 2021

📌 Commit 227f5ed has been approved by GuillaumeGomez

@bors bors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Apr 4, 2021
Dylan-DPC-zz pushed a commit to Dylan-DPC-zz/rust that referenced this pull request Apr 4, 2021
…llaumeGomez

rustdoc: Separate filter-empty-string out into its own function
bors added a commit to rust-lang-ci/rust that referenced this pull request Apr 5, 2021
Rollup of 7 pull requests

Successful merges:

 - rust-lang#80525 (wasm64 support)
 - rust-lang#83019 (core: disable `ptr::swap_nonoverlapping_one`'s block optimization on SPIR-V.)
 - rust-lang#83717 (rustdoc: Separate filter-empty-string out into its own function)
 - rust-lang#83807 (Tests: Remove redundant `ignore-tidy-linelength` annotations)
 - rust-lang#83815 (ptr::addr_of documentation improvements)
 - rust-lang#83820 (Remove attribute `#[link_args]`)
 - rust-lang#83841 (Allow clobbering unsupported registers in asm!)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
@bors bors merged commit 03bd4d2 into rust-lang:master Apr 5, 2021
@rustbot rustbot added this to the 1.53.0 milestone Apr 5, 2021
@notriddle notriddle deleted the main-js-slice-loop branch April 5, 2021 03:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. T-rustdoc Relevant to the rustdoc team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants