Why it is so slow when I try to load all the objects?

Class library usage, coding and language questions.
xbyang
Posts: 3
Joined: Tue Jan 12, 2010 12:39 am

Why it is so slow when I try to load all the objects?

Post by xbyang » Tue Jan 12, 2010 12:54 am

When I try to traverse all the children and create a object tree, it takes about 10 minutes to finish the task. Does anyone know the reason? or could please anyone tell me a faster way to load all the objects of an application?

User avatar
Support Team
Site Admin
Site Admin
Posts: 11709
Joined: Fri Jul 07, 2006 4:30 pm
Location: Graz, Austria

Re: Why it is so slow when I try to load all the objects?

Post by Support Team » Tue Jan 12, 2010 9:34 am

I don`t know exactly what you mean. Could you exlpain your issue a little bit more in detail.

I think you wan`t to add all your items in Ranorex Spy to the Ranorex Repository. Am I right?

It seems that your testing object (or even you wanna add the whole desktop) has a lot of items/subitems. In such a case, it`s not at all recommended to add all subitems to your Repository ( e.g. Visual Studio has about 30000 objects). It`s better to use the filter function (Add Matching Children to Repository) instead.

for Add Matching Children to Repository see: http://www.ranorex.com/support/user-gui ... html#c2547

Best regards,
Christian
Ranorex Team
.
Image

xbyang
Posts: 3
Joined: Tue Jan 12, 2010 12:39 am

Re: Why it is so slow when I try to load all the objects?

Post by xbyang » Thu Jan 14, 2010 6:15 am

Thank you for your reply. My algorithm is as following, it takes 10 seconds to read read the gui objects for 1 application.

private void CreateStateFromRealGUI()
{
Process process = Process.GetProcessById((int)YGUIStates.m_ProcessId);
if (process == null)
{
return;
}
try
{
foreach (Ranorex.Adapter a in Ranorex.Host.Local.Children) //Read the forms of the give process
{
string temp = a.ToString();
int i = temp.IndexOf(':');
if (i >= 0)
{
temp = temp.Substring(1, i - 1);
}
object o = a.Element.GetAttributeValue("ProcessId");
if (o != null)
{
int id = YOftenUsedFunctions.ToInt(o);
if (id == process.Id)
{
if (temp == "Form")
{
YWindow w = new YWindow();
w.relatedObj = a;
int no = m_GUIForms.Add(w);
w.ID = no;
w.ParentID = -1;
w.m_isForm = true;
w.m_WindowName = w.m_objectText;
}
}
}
}
foreach (YWindow win in m_GUIForms)
{
win.GetRealFormObjects(); //Create object tree for each window
}

}
catch { }
}

Class YWindow{ //the class of YWindow
....
public void GetRealFormObjects()
{
if (relatedObj == null) return;
GatherInfoFromAdapter((Ranorex.Adapter)relatedObj);
CreateObjects((Ranorex.Adapter)relatedObj, m_Children, -1, this);
}
void CreateObjects(Ranorex.Adapter tosearch, ArrayList subchildren, int parentID, YWindow w) //Load the object recursively
{
if (tosearch == null) return;
int c = tosearch.Children.Count;
if (c <= 0) return;
int i = 0;
for (i = 0; i < c; i++)
{
Ranorex.Adapter a = tosearch.Children;
YGUIObject obj = new YGUIObject();
int no = m_ObjectList.Add(obj);
obj.ParentID = parentID;
obj.ID = no;
obj.GatherInfoFromAdapter(a);
obj.relatedObj = a;
obj.m_Window = w;
subchildren.Add(no);
if (a.Children.Count > 0)
{
CreateObjects(a, obj.m_Children, no, w);
}
}
}
...
}

User avatar
Support Team
Site Admin
Site Admin
Posts: 11709
Joined: Fri Jul 07, 2006 4:30 pm
Location: Graz, Austria

Re: Why it is so slow when I try to load all the objects?

Post by Support Team » Fri Jan 15, 2010 10:49 am

You code walks through all UI elements of an application, depending on the number of UI elements in the application that can take some time. However, there are a few ways you can optimize your code and enhance its performance:
  • Instead of repeatedly calling Ranorex methods/properties on a single element, invoke those methods/properties only once and store the return value in a local variable. From then on use the local variable. (This is actually a general optimization technique not specific to Ranorex, but it will have a huge speed up on your code!)
    Original code:
    // getting the Children property value is time consuming,
    // since Ranorex needs to collect the children
    int c = tosearch.Children.Count;
    ...
    for (i = 0; i < c; i++)
    {
        Ranorex.Adapter a = tosearch.Children[­i];
    }
    Optimized code:
    // get Children property value only once and store in local variable
    IList<Ranorex.Unknown> childrenVariable = tosearch.Children;
    // use local variable from now on
    int c = childrenVariable.Count;
    ...
    for (i = 0; i < c; i++)
    {
        // use local variable again
        Ranorex.Adapter a = childrenVariable[­i];
    }
  • Another thing you can do is to create a Ranorex cache session whenever you access many elements in one batch. Using a cache session Ranorex retrieves all information only once from the actual UI elements (usually a slow operation), stores all data in an internal cache and from then on only uses the stored data (quick). The bad thing is that as long as the cache session is active, you always get the same data, i.e. the data Ranorex stored on the first access to the element. So, whenever your application changes, you need to end the cache session to get the up-to-date data. I recommend creating a cache session whenever you call the CreateStateFromRealGUI method, for example:
    // create a new cache session
    using (new CacheSessionContext())
    {
         CreateStateFromRealGUI();
    }
    // cache session ended
Regards,
Alex
Ranorex Support Team
.
Image