Performance Issues with Host.Local.Find

Class library usage, coding and language questions.
gwaller
Posts: 4
Joined: Wed Jun 28, 2017 7:55 pm

Performance Issues with Host.Local.Find

Post by gwaller » Thu Jul 06, 2017 5:09 pm

Greetings,


In one of my modules, I'm experiencing an issue that is becoming worse as I attempt to scale my test cases. Keep in mind, I cannot send you a snapshot of our application's structure, so whatever discussion we have will have to be high-level concepts rather than code or DOM specifics.

Following is a method that is inherited by my test cases. I'll paste the code for you to have a look at before I discuss it...
private const string Domain = "/dom[@domain='application.url']";
protected static WebDocument Document { 
     get {  return Host.Local.FindSingle<WebDocument>(new RxPath(Domain));  } } 
		
protected enum SelectionStrategy { PARENT = 0, ANCESTOR = 1 };
protected List<string> Strategies = new List<string> { "/..", "/../.." };
		
private static Duration defaultTimeout = new Duration(10000);

protected void SelectGridviewRows(
      bool single, string gdvid, string rowtext,
      SelectionStrategy strategy, Duration timeout = null)
{
       if ( timeout == null ) 
          timeout = defaultTimeout;
            
       if ( single )
       {
            // *Snip - irrelevant to this discussion 
       } 
       else
       {   
           IList<InputTag> chks = Document.Find<InputTag>(
               "//table[@id<'" + gdvid + "']//*[@innertext~'(" + rowtext + ")+?']" + 
               Strategies[(int)strategy] + 
               "//input[@id<'chkSelect']", timeout);
            foreach( InputTag chk in chks ) {
                chk.Click();
            }
        }
    }
}
The first branch of the 'if' statement is fine. It is fast and performant. The second half, however, is not. And scaling makes it worse.

I've attached a screenshot to this post of the gridview I am concerned about. As you can see, There are several rows containing "Item Type", each with a checkmark for selection. The second half of the method above will attempt to place a checkmark in each of the boxes containing "Item Type" in the content (including "Item Type Edited").

It works, to a point. The first few items are found and selected easily enough. When I add a few more items, the Document.Find<InputTag>() above will slow down. I have to add a timeout of 20-ish seconds to find 6 items. When I add another 3 (9 total) I need to add another 20 seconds to the time out. Another 3 items will take almost a minute and a half to find. Another 3 items will take up to 3 minutes.

3 minutes to find and check for 12 items in a gridview is unrealistic, as we have gridviews that contain hundreds of items.


Have you seen this issue, or something similar?

Do you have any insight you can provide to make my algorithm more performant?
Attachments
Screen Shot 2017-07-06 at 11.31.43 AM.png
Screen Shot 2017-07-06 at 11.31.43 AM.png (33.61 KiB) Viewed 722 times

ahoisl
Certified Professional
Certified Professional
Posts: 125
Joined: Fri Sep 07, 2007 8:16 am

Re: Performance Issues with Host.Local.Find

Post by ahoisl » Thu Jul 06, 2017 11:06 pm

The time to search for elements depends on the number of elements Ranorex needs to traverse. Consequently, it depends on how specific or unspecific your RanoreXPath is.

First, if you want to search relative to the "Document" element, precede the path with a ".", otherwise when you have a "/" at the start of the path Ranorex will always search from the host/root element.
Second, you use quite a lot of "//" operators in your path. Just remember that Ranorex will search all(!) descendants from there on. Try to make your RanoreXPath more specific, e.g. remove as many "//" as possible and also replace the "*" with the corresponding adapter type.
Additionally, you have an "id" in there, but use a "StartsWith" operator. If you use the full ID (with a "=" operator) to search for the table, this will also speed things up.

One more thing: You can also not specify a timeout at all, i.e. just omit that argument. Ranorex will then search the element tree exactly ones as specified by the RanoreXPath.

Regards,
Alex
Ranorex Team

gwaller
Posts: 4
Joined: Wed Jun 28, 2017 7:55 pm

Re: Performance Issues with Host.Local.Find

Post by gwaller » Mon Jul 10, 2017 5:09 pm

I got the results down to just under 30 seconds for a table with 1000+ rows.

Here is the code, for future reference:
Report.Log(ReportLevel.Info, "Mouse", "Selecting all rows containing text: " + rowtext + "'");
string xpath = 
    "dom[@domain='application.url']//table[@id<'" + gdvid + "']//" +
    "*[@innertext~'(" + rowtext + ")+?']" 
    + Strategies[(int)strategy] + 
    "//input[@id<'chkSelect']";  
IList<InputTag> chks = Host.Local.Find<InputTag>(xpath);
foreach( InputTag chk in chks )
     chk.Click();
The difference is in the usage of
Host.Local.FindSingle<WebDocument>(new RxPath(Domain));
insofar as the lookup for the DOM isn't being performed for each InputTag adapter we're trying to find.

The reply above had little of use, as using the '=' operator on an id is impossible in our application due to .NET name mangling. Additionally, since we have gridviews whose composition varies, I needed to keep the xpath as generic as possible, using the '*' operator to match any element containing the target string. In some cases, the target element might be a <span>, while in others, it might be a <td>. Who knows what it might be tomorrow.