You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Tl;dr: It's possible that Kakao could be more performant by reordering matchers to apply faster matchers first.
Since Kakao wraps Espresso, Espresso's view finding mechanism is used for actions and assertions. This mechanism will always iterate through entire view hierarchy looking for all views matching the requested predicate (source).
Most matchers should be pretty fast, however some of them will also iterate some part of view hierarchy as part of their check. For example HasDescendantMatcher or IsDescendantOfAMatcher will both go up or down the view hierarchy looking for views that match the requested descendant/ancestor. This means complexity of those matchers is not constant, contrary to simple matchers like WithIdMatcher. Moreover, when these matchers are nested, the overall performance decreases dramatically — for nested isDescendantOfA matchers, Espresso will go through every view in hierarchy, first matcher will go up in hierarchy and execute the nested matcher, which will also go up the hierarchy — I believe the complexity is non-linear in that case.
This is all unavoidable to an extent, but if those slow matchers are used within composite matchers like allOf() or anyOf(), the developer can easily improve Espresso performance by simply putting the expensive, view-traversing matchers later on the list. That way Espresso will short-circuit as soon as it can, potentially not invoking the expensive matcher at all.
If I read the code correctly, Kakao will sometimes put the slow matcher first on the list that is effectively transformed into an allOf() with same ordering, for example
. Simply switching those lines would improve the performance essentially for free, with no obvious downsides. The faster matchers will run first and short-circuit the check if they fail, and the slower matcher will run a couple of times instead of for every single view.
This might look like a small change, but especially with nested matchers the performance impact can be significant — in one project with ~270 UI tests, simply putting isDescendantOfA and hasDescendant matchers last in allOf calls cut total test run time in half (the project doesn't use Kakao).
The text was updated successfully, but these errors were encountered:
lwasyl
changed the title
Potential performance problem with hierarchy-traversing matchers
Potential performance optimisation around hierarchy-traversing matchers
Apr 12, 2023
Tl;dr: It's possible that Kakao could be more performant by reordering matchers to apply faster matchers first.
Since Kakao wraps Espresso, Espresso's view finding mechanism is used for actions and assertions. This mechanism will always iterate through entire view hierarchy looking for all views matching the requested predicate (source).
Most matchers should be pretty fast, however some of them will also iterate some part of view hierarchy as part of their check. For example
HasDescendantMatcher
orIsDescendantOfAMatcher
will both go up or down the view hierarchy looking for views that match the requested descendant/ancestor. This means complexity of those matchers is not constant, contrary to simple matchers likeWithIdMatcher
. Moreover, when these matchers are nested, the overall performance decreases dramatically — for nestedisDescendantOfA
matchers, Espresso will go through every view in hierarchy, first matcher will go up in hierarchy and execute the nested matcher, which will also go up the hierarchy — I believe the complexity is non-linear in that case.This is all unavoidable to an extent, but if those slow matchers are used within composite matchers like
allOf()
oranyOf()
, the developer can easily improve Espresso performance by simply putting the expensive, view-traversing matchers later on the list. That way Espresso will short-circuit as soon as it can, potentially not invoking the expensive matcher at all.If I read the code correctly, Kakao will sometimes put the slow matcher first on the list that is effectively transformed into an
allOf()
with same ordering, for exampleKakao/kakao/src/main/kotlin/io/github/kakaocup/kakao/recycler/KRecyclerView.kt
Lines 87 to 90 in da02133
Kakao/kakao/src/main/kotlin/io/github/kakaocup/kakao/edit/KTextInputLayout.kt
Lines 35 to 38 in da02133
This might look like a small change, but especially with nested matchers the performance impact can be significant — in one project with ~270 UI tests, simply putting
isDescendantOfA
andhasDescendant
matchers last inallOf
calls cut total test run time in half (the project doesn't use Kakao).The text was updated successfully, but these errors were encountered: