-
Notifications
You must be signed in to change notification settings - Fork 784
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
Performance of axe.utils.select('*') is slow with lots of nodes #702
Comments
This code returns the nodes in the document order, ordered by selector. So for example if a rule looks for We would have to expose a property in all rules to indicate whether they require sorted nodes and then make this sort conditional @WilcoFiers @marcysutton thoughts? |
Hmmm.. If that's a little hairy, how about memoizing |
Agreed. Memoization seems like a sensible approach, although we'd have to make sure it's cleaned reset after every run. |
@paulirish @WilcoFiers memoizing select will reduce the number of sorts from 56 to 40 (if you run all the rules). This is based on some code I wrote quickly to parse all the selectors in all the rules and then compare the parsed selectors stringified. I could write a more accurate comparitor but I don't think the difference is going to be huge. So we are talking about eliminating ~30% of this time. In order for a check to be able to take advantage of the order of elements returned, it has to do one of two things:
I have reviewed all the checks that have an after function and only heading order relies on the order I have reviewed all the checks and can find no use of it within the builtin checks This means we can eliminate 98.3% of the time by adding an attribute to the rules object and only sorting when we see that. Given that we are talking about a major release, I would prefer to make this change now - thoughts? |
I don't think we should return nodes out of order in the DOM. I've seen what that looks like in the extension, and it's quite confusing. I don't like having this as an option, even if it's on by default, it exposes a design flaw, which I think isn't very clean. I think maybe a smarter way to do this is to build QSA in such a way that it can't return elements out of order. If instead of going through each expression in the selector one at a time, we consider all of them as we're walking this composed DOM, we can keep them in order. QSA is a little more complicated because of it, but we would never have to sort the results. |
One alternative idea... What if you only do this sort when there's a |
That could work. We'd have to sort and deduplicate the context object to make that work I think. We might as well move node sorting into QSA. Easier to do it there, and it should probably always have its results sorted. I still think we should memoize |
ok, I think memoizing the results and changing QSA to return guaranteed sorted results would be the best outcome. Assuming no new performance issues, that would get us 100% elimination of the sort plus 30% elimination of the QSA work. |
Awesome. @paulirish are you interested to work on a PR for this? |
@paulirish @WilcoFiers if neither of you has done anything on this by Saturday, I will take a shot at it myself at the weekend |
@paulirish Implemented the first half of this, you can download the axe.js file https://gist.github.com/dylanb/37509ec425d0b00331caa25963b093d4 I am seeing about a 7% improvement in performance by eliminating the sort (mlb.com goes down to 13s from 14s) - not as much as I was expecting. I would appreciate a gander at the changes for suggestions as to whether there are parts of the code that might not be optimizable or alternative approaches that might exhibit better performance. I estimate that memoization of select will give us another 4% at most |
Ok, I memoized Here is the gist https://gist.github.com/dylanb/fc6e4d6af4c68566218f65562328f37e |
@dylanb if you're still around, drop by https://gitter.im/dequelabs/axe-core if not, i'll be around on a weekday. |
fix(perf): improve select performance fixes #702
Example trace: https://chromedevtools.github.io/timeline-viewer/?loadTimelineFromURL=drive://1qJeP82OwoRZ0g4PS-bvJuf_FKI0UfIEm
The above trace is of the mlb homepage with a dev build of axe (including both #699 and #701)
You can see these pretty big chunks of array sorting:
Looking into it, it appears to be when
axe.utils.select
is called with aselector
of*
and then does the sort() to get document order. Do we need these results in an order other than what qSA returns?The text was updated successfully, but these errors were encountered: