我正在努力提高某些UI自动化操作的速度。我偶然发现了(不太好)有记录的缓存可能性。
根据我的理解,整个操作(如果你有一个大的GUI树)是如此之慢,因为对于每一个函数调用都必须有一个进程更改(有点像转到内核模式,我想,速度方面?!)。所以..来缓存。
只需告诉函数缓存元素及其子元素,然后快速处理它。 (根据我的理解,您只需要进行一次上下文更改,并一次性汇总所需的所有数据。)
好主意,但是......对于我来说,与未缓存的变体一样慢。我写了一些简单的测试代码,看不出改进。
AutomationElement ae; // element whose siblings are to be examined, thre are quite a few siblings
AutomationElement sibling;
#region non-cached
watch.Start();
for (int i = 0; i < 10; ++i)
{
sibling = TreeWalker.RawViewWalker.GetFirstChild(TreeWalker.RawViewWalker.GetParent(ae));
while (sibling != null)
{
sibling = TreeWalker.RawViewWalker.GetNextSibling(sibling);
}
}
watch.Stop();
System.Diagnostics.Debug.WriteLine("Execution time without cache: " + watch.ElapsedMilliseconds + " ms.");
#endregion
#region cached
watch.Reset();
watch.Start();
CacheRequest cacheRequest = new CacheRequest();
cacheRequest.TreeScope = TreeScope.Children | TreeScope.Element; // for testing I chose a minimal set
AutomationElement parent;
for (int j = 0; j < 10; ++j)
{
using (cacheRequest.Activate())
{
parent = TreeWalker.RawViewWalker.GetParent(ae, cacheRequest);
}
int cnt = parent.CachedChildren.Count;
for (int i = 0; i < cnt; ++i)
{
sibling = parent.CachedChildren[i];
}
}
watch.Stop();
System.Diagnostics.Debug.WriteLine("Execution time parentcache: " + watch.ElapsedMilliseconds + " ms.");
#endregion
设置是:你得到一个元素,并想要检查所有(许多)兄弟姐妹。给出了没有缓存和缓存的两种实现。
输出(调试模式): 没有缓存的执行时间:1130毫秒。 执行时间parentcache:1271 ms。
为什么这不起作用?如何改进?
感谢任何想法!!!
答案 0 :(得分:2)
我不希望这两个循环的运行时间差异很大,因为在这两种情况下,父项的子项必须完全行走(在第一次显式中,在第二次中填充缓存。)我确实认为,虽然,循环遍历parent.CachedChildren
数组所需的时间远远低于初始步行代码。此时,应该缓存元素,并且可以在不重新遍历树的情况下使用它们。
一般情况下,您无法免费获得性能,因为您需要花时间在缓存变得有用之前实际填充缓存。
答案 1 :(得分:0)
实际上,最近我找到了再次检查它的时间,也反映了不同的UI元素。 为了使缓存更快,首先必须指定所有(并且仅)所需的元素。 如果你有一个真正的性能差异。 G。看看一个内部有100个元素或类似内容的ComboBox,就像一个非常复杂的GUI,在同一层次结构层面上有很多元素 - 你实际上需要来自所有元素的数据。 所以..缓存不是一个解决方案,而是一个性能优化工具,必须应用...有关情况,需求和内部工作的知识。 BTW,谈到性能,我发现每个。当前访问UI元素的时间大约需要20ms,因此对于复杂的操作,这真的可以达到很长的时间。