axe-core icon indicating copy to clipboard operation
axe-core copied to clipboard

`axe.runPartial` performance on page with 100k nodes

Open straker opened this issue 1 year ago • 6 comments

We recently ran into an issue where a page had 108,000 option nodes in a single select element. Axe-core took a bit to just process that many nodes, but the real problem was processing selectors for that many nodes.

Typically our answer to that is to use resultTypes to filter out most nodes which allows us to just generate selectors for things like violations. However when using runPartial the resultTypes option is not used which means the at the end of the runPartial all 108,000 nodes will try to generate a selector even if they will be removed after running finishRun.

One thing we'll have to figure out is how to deal with rules that have after methods which may change the result of a node.

straker avatar Apr 24 '24 19:04 straker

We're going to do a few different things to address this problem.

First, there are some small improvements we can make to the getSelector code to handle generating selectors for an element with many children. We can detect that and prefer to use nth-child first rather than going through other indicators (such as id, class, etc.).

Second, a workaround for the performance problem could be to disable selectors in the run options in order to avoid generating them. This would then require having ancestors enabled in order to still get information about where an element is in the DOM when it fails. Generating ancestors is faster but still has performance problems with so many nodes. We can apply the same type of fix from getSelector in the previous point to generating ancestors as well.

Lastly, we'd like to make this switch from selectors to ancestors more dynamic to help speed up performance. We're going to allow the selectors run option to additional be a string with two options: ancestor or dynamic. Setting it to ancestor will make the target property of a node use the ancestor generation rather than the selector generation. dynamic will do this change based on the size of the page. For pages with a very large number nodes (number to be determined) axe will automatically use ancestor generation, where as for anything smaller than the very large number will use selector generation as it does today.

straker avatar Apr 25 '24 19:04 straker

See also #4273

dbjorge avatar May 29 '24 00:05 dbjorge