Performance: write<->appendChild
jack
- javascript
Hallo,
ich habe zum Zeichnen bislang die Grafikbibliothek von Walter Zorn genommen. Für meine spezielle Anwendungen kann ich diese aber nicht benutzen, da ich spezielle Funktionen brauche. Also sitze ich nun hier und fange von vorne an. Bei einem Performancevergleich schneidet meine nun deutlich schlechter ab (Dafür brauche ich aber auch weniger Ebenen :-)). Mit Hauptursache für die schlechte Performance (Faktor 20) war folgdendes:
this.setPixel = function(divID,x,y,colour) {
var dv=document.createElement("div");
dv.style.background = colour;
dv.style.width="1px";
dv.style.height="1px";
dv.style.position="absolute";
dv.style.left=x;
dv.style.top=y;
dv.id=divID;
}
Ersetze ich die Funkion durch
this.setPixel = function(divID,x,y,colour) {
document.write("<div id='"+divID+"' style='position:absolute;background-color:"+colour+";top:"+y+"px;left:"+x+"px;width:1px;height:1px;'></div>");
}
so ist es deutlich schneller, wenn auch immer noch um den Faktor 4 bis 5 langsamer, was aber woh für die Ebenenoptimierung draufgeht. Vielleicht bekomme ich das aber noch runter.
Kann mir jetzt jemand sagen, warum write schneller ist. Ich dachte das ist langsamer. Hat sonst noch jemand eine Idee, wie es schnell geht?
Hallo jack.
Kann mir jetzt jemand sagen, warum write schneller ist. Ich dachte das ist langsamer.
The write()-Methode gibt einfach nur Zeichendaten aus; an welcher Stelle (sprich: in welchem Umfeld) dies geschieht, ist ihr ziemlich egal.
→ wir schütten einen Eimer Farbe auf die Wand
Die DOM-Methoden zum Einhängen in den Dokumentenbaum dagegen bedürfen erst eines Knotens, welcher Kindknoten erhalten darf. Dort hängen sie dann den neuen Kindknoten fein säuberlich ein.
→ wir ziehen mit einem Pinsel auf der Wand saubere Linien von oben nach unten und umgekehrt und vermeiden das vollpinseln von Fensterrahmen o. Ä.
Einen schönen Samstag noch.
Gruß, Ashura
Das heißt, dass die erste Methode schnell aber nicht so gut ist. Und die zweite genau umgekehrt? Was würdest du denn empfehlen?
Und noch eine Frage:
Der andere Bereich wird wohl an sowas liegen:
curDiv = document.getElementById(lastDivId);
curHeight = curDiv.style.height;
newHeight = curHeight.substring(0,curHeight.length-2);
newHeight++;
curDiv.style.height = newHeight+"px";
Der ganze Block ist nur dazu da, das div um 1px höher zu machen. Kann man das nicht schneller machen? Die substring-Methode wird hier wohl die Bremse sein.
Hallo jack.
Das heißt, dass die erste Methode schnell aber nicht so gut ist. Und die zweite genau umgekehrt? Was würdest du denn empfehlen?
Da dir Performance wichtig ist, musst du wohl die write()-Methode verwenden.
Ob innerHTML noch einen Vorteil bringen könnte (sozusagen als Mittelweg), vermag ich nicht zu sagen.
Der ganze Block ist nur dazu da, das div um 1px höher zu machen. Kann man das nicht schneller machen?
Die aktuelle Höhe eines Objektes kannst du mit http://de.selfhtml.org/javascript/objekte/all.htm#offset_height@title=offsetHeight auslesen, du erhältst praktischerweise einen Wert in Pixeln, welchen du weiterverarbeiten kannst.
Einen schönen Samstag noch.
Gruß, Ashura
Die aktuelle Höhe eines Objektes kannst du mit http://de.selfhtml.org/javascript/objekte/all.htm#offset_height@title=offsetHeight auslesen, du erhältst praktischerweise einen Wert in Pixeln, welchen du weiterverarbeiten kannst.
Witzigerweise ist es aber nicht mal schneller.
newHeight = curDiv.offsetHeight+1;
curDiv.style.height = newHeight+"px";
führt zu einer Verlangsamung um 2 im Vergleich zu
newHeight = curDiv.style.height;
newHeight = curHeight.substring(0,curHeight.length-2);
newHeight++;
curDiv.style.height = newHeight+"px";
Hallo jack.
newHeight = curDiv.offsetHeight+1;
curDiv.style.height = newHeight+"px";
Warum die Zwischenspeicherung?
`curDiv.style.height = (curDiv.offsetHeight + 1) + 'px';`{:.language-javascript}
> führt zu einer Verlangsamung um 2 im Vergleich zu
Und mit obiger Anpassung?
Im Zweifelsfall bleibt dir wohl wirklich nur Trial and Error, um die performanteste Methode zu finden.
Einen schönen Samstag noch.
Gruß, Ashura
--
sh:( fo:} ch:? rl:( br: n4:~ ie:{ mo:| va:) de:> zu:} fl:( ss:) ls:[ js:|
[<mathbr:del.icio.us/>](http://del.icio.us/mathbr) [<mathbr:w00t/>](http://w00t.noctus.net)
Hallo,
curDiv = document.getElementById(lastDivId);
curHeight = curDiv.style.height;
newHeight = curHeight.substring(0,curHeight.length-2);
newHeight++;
curDiv.style.height = newHeight+"px";Der ganze Block ist nur dazu da, das div um 1px höher zu machen. Kann man das nicht schneller machen? Die substring-Methode wird hier wohl die Bremse sein.
Man nimmt dafür gängigerweise parseInt, ich weiß aber nicht, ob das bedeutend schneller ist.
Du könntest die Pixelhöhe ohne Einheit aber auch in einer Eigenschaft speichern, wenn du das div erzeugst. Dann machst du nur curDiv.hoehe++; curDiv.style.height = curDiv.hoehe + "px";
Mathias
Hallo,
The write()-Methode gibt einfach nur Zeichendaten aus; an welcher Stelle (sprich: in welchem Umfeld) dies geschieht, ist ihr ziemlich egal.
Im Gegentum, es ist völlig determiniert, an welcher Stelle dies geschieht.
Die DOM-Methoden zum Einhängen in den Dokumentenbaum dagegen bedürfen erst eines Knotens, welcher Kindknoten erhalten darf. Dort hängen sie dann den neuen Kindknoten fein säuberlich ein.
Ich verstehe deinen Kritikpunkt nicht. Ob ich jetzt ein script-Element im body notiere, wo ich document.write() aufrufe, oder mit appendChild Elemente an den body anhänge, der Elementenbaum kann letztlich derselbe sein.
Der entscheidende Punkt ist doch eher, dass document.write() eben nur dort Elemente hinschreiben kann, wo das zugehörige script-Element notiert ist (Netscape 4 mit seinen vielen documents mal außen vor).
Mathias
Hallo molily.
The write()-Methode gibt einfach nur Zeichendaten aus; an welcher Stelle (sprich: in welchem Umfeld) dies geschieht, ist ihr ziemlich egal.
Im Gegentum, es ist völlig determiniert, an welcher Stelle dies geschieht.
Je nachdem, wo der betreffende Scriptblock notiert wurde, kann dies der Fall sein, ja.
Ich verstehe deinen Kritikpunkt nicht.
Was ist wohl performanter?
<body>
<script type="text/javascript">
[code lang=javascript]var myURIs = ['Foo', 'Bar', 'Baz', 'Qux'];
document.write('<ul>');
for (var i = 0; i < myURIs.length; i++) {
document.write('<li><a href="/' + myURIs[i] + '">' + myURIs[i] + '</a></li>');
}
document.write('</ul>');
</script>
</body>[/code]
Versus:
<head>
<script type="text/javascript">
[code lang=javascript]window.addEventListener('load', function() {
var myUl = document.createElement('ul');
var myURIs = ['Foo', 'Bar', 'Baz', 'Qux'];
for (var i = 0; i < myURIs.length; i++) {
var myA = document.createElement('a');
myA.href = '/' + myURIs[i];
myA.appendChild(document.createTextNode(myURIs[i]));
var myLi = document.createElement('li');
myLi.appendChild(myA);
myUl.appendChild(myLi);
}
document.body.appendChild(myUl);
}, false);
</script>
</head>
<body></body>[/code]
Ob ich jetzt ein script-Element im body notiere, wo ich document.write() aufrufe, oder mit appendChild Elemente an den body anhänge, der Elementenbaum kann letztlich derselbe sein.
Natürlich, darum ging es mir auch gar nicht, sondern rein um die Performance. (Das Maß aller Dinge ist hier Jacks Performancetest.)
Der entscheidende Punkt ist doch eher, dass document.write() eben nur dort Elemente hinschreiben kann, wo das zugehörige script-Element notiert ist (Netscape 4 mit seinen vielen documents mal außen vor).
Das kommt noch hinzu, dürfte für Jack aber nicht relevant sein.
Einen schönen Sonntag noch.
Gruß, Ashura
Hallo,
die schnellste Methode afai(k/r) ist
while(irgendwas)
{
myarray.push('<html>zeuch</html>');
}
mynode.innerHTML = myarray.join("");
gruss
*seufz*
in den bookmarks gewühlt: http://www.quirksmode.org/dom/innerhtml.html
beachte auch http://www.quirksmode.org/dom/classchange.html
wer die richtigen tags weiss, der findet :]
gruss
Hallo,
ich verstehe deine Frage nicht. document.write() und innerHTML bzw. DOM-Manipulationen sind fundamental für andere Zwecke geeignet.
this.setPixel = function(divID,x,y,colour) {
Das lässt mich vermuten, dass du einen instantiierten Prototyp hast, deren Methoden du zu irgendeinem Zeitpunkt aufrufst. Solange du innerHTML oder createElement/appendChild verwendest, geht das auch.
Wenn du document.write() verwendest, musst du auf jede Event-Steuerung verzichten. Dann kannst du die Methoden nur in einem script-Element im body-Element aufrufen, der während des Ladens ausgeführt wird und eben an diese Stelle ein Element schreibt.
Solange du alle Methoden nur beim Laden des Dokuments im body aufrufst und diese dann tausende div-Elemente schreiben, so spricht nichts gegen document.write. Wenn du nach dem Laden aber irgendetwas zeichnen willst, so funktioniert document.write nicht.
Mathias
Hallo jack,
wieviele Pixel pro Sekunde schaffst du denn? Mit meiner Bibliothek schaffe ich im IE auf der Seite http://www.j-berkemeier.de/LogistischeAbbildung.html (100 Iterationen) 17000 SPANs in ca 10 Sekunden, wobei auch noch "etwas" gerechnet werden muss. Der FF braucht leider etwa 90 Sekunden. Rechner ist ein 3.2 Ghz P4 (640)
Ich erzeuge übrigens die SPANs durch Klonen eines schon entsprechend konfigurierten Musters und muss mich dann nur noch um x, y, und Farbe kümmern.
Wieviele Pixel/s schafft die Bibliothek von Walter Zorn?
Gruß, Jürgen