3 Stimmen

Die Verwendung von Caching mit AutomationElements bringt mir keinen Geschwindigkeitszuwachs - beabsichtigt oder falsch verwendet?

Ich versuche, die Geschwindigkeit einiger UI-Automatisierungsvorgänge zu erhöhen. Ich bin über die (nicht so gut) dokumentierte Möglichkeit des Caching gestolpert.

Soweit ich das verstanden habe, ist die ganze Operation (wenn man einen großen GUI-Baum hat) so langsam, weil für jeden einzelnen Funktionsaufruf ein Prozesswechsel stattfinden muss (ähnlich wie im Kernel-Modus, nehme ich an, geschwindigkeitsmäßig?!). Also kommt Caching ins Spiel.

Sagen Sie der Funktion einfach, dass sie ein Element und seine Kinder zwischenspeichern soll, und arbeiten Sie dann blitzschnell daran (soweit ich weiß, haben Sie nur einen Kontextwechsel und stellen alle benötigten Daten in einem Zug zusammen).

Gute Idee, aber es ist für mich genauso langsam wie die nicht gecachte Variante. Ich schrieb einige einfache Testcode, und konnte nicht sehen, eine Verbesserung.

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

Der Aufbau ist folgender: Sie erhalten ein Element und wollen alle seine (vielen) Geschwister überprüfen. Beide Implementierungen, ohne und mit Cache, sind gegeben.

Die Ausgabe (Debug-Modus): Ausführungszeit ohne Cache: 1130 ms. Ausführungszeit parentcache: 1271 ms.

Warum funktioniert das nicht? Wie kann man es verbessern?

Danke für jede Idee!!!

2voto

dlev Punkte 47336

Ich würde nicht erwarten, dass sich die beiden Schleifen in ihrer Laufzeit stark unterscheiden, da in beiden Fällen die Kinder des Elternteils vollständig durchlaufen werden müssen (in der ersten explizit und in der zweiten, um den Cache aufzufüllen). Ich denke jedoch, dass die Zeit, die für das Durchlaufen der parent.CachedChildren Array ist viel niedriger als Ihr ursprünglicher Walk Code. Zu diesem Zeitpunkt sollten die Elemente zwischengespeichert sein, und Sie können sie verwenden, ohne den Baum erneut durchlaufen zu müssen.

Der allgemeine Punkt ist, dass man Leistung nicht umsonst bekommt, da man die Zeit investieren muss, um den Cache tatsächlich zu füllen, bevor er nützlich wird.

0voto

Andreas Reiff Punkte 7205

Kürzlich habe ich die Zeit gefunden, sie erneut zu überprüfen, und zwar auch mit verschiedenen UI-Elementen. Damit das Caching schneller wird, muss man zunächst alle (und nur die) benötigten Elemente angeben. Es gibt einen echten Leistungsunterschied, wenn man sich z. B. eine ComboBox mit 100 Elementen oder etwas Ähnliches ansieht, wie eine sehr komplizierte GUI mit vielen Elementen auf derselben Hierarchieebene - und man braucht die Daten von allen Elementen. Caching ist also keine Lösung für alles, sondern eher ein Performance-Optimierungs-Tool, das mit Wissen über die Situation, die Anforderungen und die interne Arbeitsweise angewendet werden muss. Apropos Leistung: Ich habe herausgefunden, dass jeder aktuelle Zugriff auf ein UI-Element etwa 20 ms dauert, was bei komplexen Vorgängen wirklich eine beträchtliche Zeitspanne ausmachen kann.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X