Why it is so slow when I try to load all the objects?
Why it is so slow when I try to load all the objects?
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?
- Support Team
- Site Admin
- Posts: 12145
- Joined: Fri Jul 07, 2006 4:30 pm
- Location: Houston, Texas, USA
- Contact:
Re: Why it is so slow when I try to load all the objects?
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
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
Re: Why it is so slow when I try to load all the objects?
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);
}
}
}
...
}
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);
}
}
}
...
}
- Support Team
- Site Admin
- Posts: 12145
- Joined: Fri Jul 07, 2006 4:30 pm
- Location: Houston, Texas, USA
- Contact:
Re: Why it is so slow when I try to load all the objects?
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:
Alex
Ranorex Support Team
- 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
Alex
Ranorex Support Team