Performancebetrachtung typischer XML-Operationen Seminar XML und intelligente Systeme Wintersemester 05/06 Uni Bielefeld 07.11.2005 Janick Martinez [email protected] 1 Lebenszyklus eines XML-Dokuments Parsen 07.11.2005 Zugriff Modifikation Janick Martinez Serialisierung 2 / 19 Gliederung des Vortrages Komplexitätsanalyse XML-Dokumente im Speicher elementare XML-Operationen Zugriff auf bestimmte Knoten Testrelationen Datenstruktur-Modifikationen komplexe XML-Operationen 07.11.2005 Janick Martinez 3 / 19 Komplexitätsanalyse Einteilung von Algorithmen in Komplexitätsklassen O(f) „obere Schranke“ Θ(f) „obere und untere Schranke“ Ω(f) „untere Schranke“ „Reduktion auf Funktion der höchsten Ordnung und Abstraktion von konstanten Faktoren“ O(n²) Beispiel: 5n²+3n O(?) Die Funktion 5n²+3n „wächst im wesentlichen nicht schneller“ als die Funktion n² 07.11.2005 Janick Martinez 4 / 19 Beispiel Komplexitätsanalyse min = array[0] Schleife wird n-1 max = array[0] mal ausgeführt i = 1 while (i < array.length()) if(array[i] < min) then Pro Durchlauf je min = array[i] weils ein Vergleich if(array[i] > max) then max = array[i] i++ end 2(n-1) Funktion zur Ermittlung des Mini- / Maximums eines Arrays Bestimmende Eingabegröße: Länge des Arrays Bestimmende Operation: „Vergleichen“ Zeitkostenfunktion T(n) = 2(n-1) O(n) Ermittlung des Mini- / Maximums erfordert lineare Zeit 07.11.2005 Janick Martinez 5 / 19 Bestimmende Eingabegrößen Gesamtanzahl an Elementen Bibliothek number of elements Buch 1 Buch n m Anzahl Kinder eines Knotens fanout Buch 2 „typisch“ < 10 Autor Titel ISBN Ausleihliste Tiefe des Baumes depth 07.11.2005 „typisch“ 8 - 13 Janick Martinez Entleiher 1 Entleiher n 6 / 19 XML-Elementen im Speicher Kind 2 Feld-Indices Felder (arrays) 1 2 3 4 Kern: indizierte Feld-Elemente sehr schneller Zugriff in konstanter Zeit O(1) Speicherschonend O(n) Unvorteilhaft im Zusammenhang mit Datenstrukturmodifikationen 07.11.2005 Janick Martinez Children[ ] … Kind x Children[ ] Knoten x Children[ ] … Kind n … n-1 n Children[ ] … 7 / 19 XML-Elementen im Speicher Verknüpfte Liste (Linked-Lists) Kern: Referenzen auf Knoten Relativ schneller Zugriff O(n) Etwas speicherbelastender als Arrays Knoten myParent firstChild nextSibling … O(n + fanout*depth) Hierarchische Struktur leicht aufzubauen Vorteilhaft im Zusammenhang mit Datenstrukturmodifikationen 07.11.2005 Kind 1 Kind 2 Kind 3 myParent myParent myParent firstChild nextSibling … firstChild nextSibling … firstChild nextSibling … Janick Martinez 8 / 19 XML-Elementen im Speicher Auslassende Liste (Skip-Lists) Spezielle Erweiterung einer Linked-List Auf Wahrscheinlichkeitsverteilungen basierend Kopf Schneller Zugriff auf einzelne Elemente Terminator O(log(n)) Nur geringfügig erhöhter Speicherverbrauch Erst sinnvoll bei größerem fanout max Layer n´ter Layer 07.11.2005 Janick Martinez Kind 1 Kind 2 Kind 3 Kind 4 Kind 5 9 / 19 Zugriff auf bestimmte Knoten Datenstruktur Operation Array Knoten mit ID/Key X O(number of elements) • seriell ≈ O(1) • per Suchliste (z.B. HashTable) O(1) N-te Kind von Knoten Y Attribut- und Textzugriff eines Knoten Linked-List Skip-List O(fanout) O(log(fanout)) O(1) Attribute Text direkt mit Knoten assoziiert Suchlisteund Verwendung vomvon Parser Referenzen aufgebaut firstChild und nextSibling Speicherung innerhalb Kostet zusätzliche Zeitdes Knotens Referenzierung 07.11.2005 der Daten Janick Martinez 10 / 19 Mögliche Gefahr durch getChildN() i = 0 Beabsichtigt: ersten N Kinder eines Knotens erhalten while (i < lastChildNumber) child = parentNode.getChildN(i) Hier: getChildN() mit Referenzen firstChild und nextSibling myNodeList.add(node) realisiert i++ end O(fanout²) Bessere Alternative: direkter Gebrauch der nextSibling Referenz des gefundenen Kindes O(fanout) 07.11.2005 Janick Martinez 11 / 19 Zugriff auf andere Verwandte Am Beispiel vorherigen Geschwister 1. Wie im vorherigen Code-Beispiel Rechenintensiv 2. Durch zusätzliche Referenzen Speicherintensiv Allgemeiner Trade-Off Rechenzeit 07.11.2005 Speicher Janick Martinez 12 / 19 Testrelationen Datenstruktur Operation Array Linked-List Skip-List X.isSiblingOf(Y) O(1) X.isChildOf(Y) O(1) O(depth) X. isDescendantOf(Y) Überprüfung, == Y Iteration über ob alleX.getParent() Vorfahren von X mittels == Überprüfung, Y.getParent() X.getParent() und ob Y gefunden wurde 07.11.2005 Janick Martinez 13 / 19 Beispiel: X.isDescendantOf(Y) parentNode = nodeX.getParent() wird maximal depth-1 while (parentNode != null) mal ausgeführt if(parentNode == nodeY) then return true parentNode = parentNode.getParent() end return false O(depth) 07.11.2005 Janick Martinez 14 / 19 Datenstrukturmodifikationen Datenstruktur Operation Array Linked-List Skip-List Knoten einfügen O(fanout) O(fanout) / O(1) O(log(fanout)) / O(1) Knoten löschen O(fanout) O(fanout) / O(1) O(log(fanout)) / O(1) Knoten bewegen O(fanout) O(fanout) O(log(fanout)) Ebenfalls Einfügposition hoher kann konstanter in logarithmischer Faktor wie beim Zeitzuermittelt Einfügen Problem von Arrays: Begrenzte linearer Zeit Größe gefunden werden Laufzeit wie Reduziert sich beim auf Einfügen das Löschen abhängig des Knotens von aktualisierenden an derwerden alten und Konstanter Faktor jedoch leicht höher als bei einerZeit Linked-List Laufzeit Array muß abhängig von zu werden, aktualisierenden benötigt lineare Referenzen auf Referenzen Einfügen anneu und derangelegt neuen Bezügen Position und des neuen KnotensFaktor sowiesehr von Bezügen wie Aber:innerhalb impraktikabeler konstanter hoch „Anzahl Kinder“, Kosten hierfür aber konstant Architekturabhängig 07.11.2005 1. Kinder des eingefügten Knotens direkt mit eingefügt 2. Vorgang muss iterativ für jedes Kind wiederholt werden Janick Martinez 15 / 19 Beispiel: Einfügen in Linked-List O(1) parentNode.incrementChildNumber() newNode.setParent(parentNode) if(n == 0) then newNode.setFollowing(parentNode.getFirstChild()) O(1) parentNode.setFirstChild(newNode) return precidingSibbling = parentNode.getFirstChild() i = 1 wird maximal fanout-1 mal ausgeführt O(fanout) while (i < n) precidingSibbling = precidingSibbling.getNextSibbling() i++ end newNode.setFollowing(precidingSibbling.getNextSibbling()) precidingSibbling.setNextSibbling(newNode) O(1) Funktion zum Einfügen eines neuen Knotens newNode an die Stelle n O(fanout) 07.11.2005 Janick Martinez 16 / 19 Komplexe XML-Operationen Komplexe XML-Operationen Machen starken Gebrauch und sind zusammengesetzt aus elementaren Operationen Laufzeit der primitiveren Operationen ist ausschlaggebend für die der komplexeren Operationen 07.11.2005 Janick Martinez 17 / 19 Beispiel: Alle Kinder mit Attribut X = Y O(fanout) children = node.getChildren() O(fanout) while (children.hasNext()) currentChild = children.next() if (currentChild.getAttribute(X) == Y) then myNodeList.add(currentChild) O(1) end return myNodeList Funktion zur Ermittlung aller Kinder eines Knotens mit bestimmten Attribut XPath: /node/child[@X=Y] Nutzt primitivere Operationen getChildren() und getAttribute() O(fanout) Laufzeitabhängigkeit von elementaren Operationen Bspw: schlechtere Implementierung von getChildren() mit O(fanout²) O(fanout²) 07.11.2005 Janick Martinez 18 / 19 Fazit Interne API Implementierung sollte bekannt sein und berücksichtigt werden, um effiziente XML verarbeitende Programme zu erstellen XML bringt keine neuen Erkenntnisse im Bezug auf effiziente Datenverarbeitung, sondern baut auf verlässlichen Algorithmen auf Zum Abschluss: Beispielhaftes Benchmark der XOM Java Implementierung Quellen S. DeRose, „Architecture and Speed of Common XML Operations“, Extreme Markup Languages 2005, August 2005 Google… 07.11.2005 Janick Martinez 19 / 19 Benchmark XOM API 1. Element einfügen Vom Anfang an das Ende Vom Ende zum Anfang Am Beginn In die Mitte An das Ende 2. Element bewegen 3. Bewegen komplexer Elemente REC Größe(bytes) 159339 Markup Dichte 34% 07.11.2005 chrmed med chrbig 893821 1264240 3417181 6% 33% Janick Martinez 2% big 5052472 33% 20 / 19