Geschwindigkeit von CSS-Selektoren
suit
- css
Hallo,
ich hab' eine ungewöhnliche Frage :)
Kürzlich hab' ich irgendwo ein Benchmark zur Geschwindigkeit von JavaScript-Selektor-Engines gesehen. Die meisten Engines arbeiten deutlich schneller wenn man man anstatt #foo z.B. div#foo im Selektor notiert auf jQuery trifft das besonders zu).
Nun die Frage: ist das auch für CSS selbst relevant - sprich ist der Browser schneller wenn er div#foo selektiert oder doch lieber *[id=foo].
Natürlich ist dieses Beispiel sehr theoretisch - aber wie siehts mit banaleren dingen aus: div.foo vs. .foo vs. div#foo vs. #foo - wobei das Element nur 1x vorkommt.
Ist ist eine Klasse schneller gefunden oder eine ID - bedeutet das Element einen Geschwindigkeitsvorteil?
Ich stelle mir hierbei besonders komplexe Seiten mit viel HTML und CSS vor - solche Dinge machen langsamen Browsern - wie z.B. dem Internet Explorer 6 - teilweise sehr zu schaffen. Lässt sich hier noch Geschwindigkeit rausholen, ohne die HTML-Struktur zu vereinfachen?
Danke
Moin Moin,
ich vertraue dem folgenden Mozilla Artikel: https://developer.mozilla.org/en/Writing_Efficient_CSS
Dort steht drin, dass CSS-Selektoren von rechts nach links abgearbeitet werden. dh. bei div#foo wird erst nach dem Element mit der ID foo gesucht und dann überprüft, ob es ein div ist. Da IDs per Definition einzigartig sind, reicht #foo vollkommen aus.
Wie jQuery bzw Sizzle das händelt ist mir leider unbekannt. Allerdings würde ich auch hier sagen, weniger ist mehr.
Zu guter Letzt ist div#foo schlechter Stil. Schließlich sind IDs dazu da um ein Element eindeutig zu identifizieren. Wenn ich einen Dieb an Hand eines Fingerabdruckes( einzigartig) ermittelt habe, muss ich ja auch nicht extra prüfen, ob er auf die Beschreibung eines mittelgroßen dunkelblonden Mannes mit weiblicher Statur zutrifft.
Mfg Hase
Hi,
Zu guter Letzt ist div#foo schlechter Stil. Schließlich sind IDs dazu da um ein Element eindeutig zu identifizieren. Wenn ich einen Dieb an Hand eines Fingerabdruckes( einzigartig) ermittelt habe, muss ich ja auch nicht extra prüfen, ob er auf die Beschreibung eines mittelgroßen dunkelblonden Mannes mit weiblicher Statur zutrifft.
Nicht alles, was hinkt ...
Eine ID hat nicht die Eindeutigkeit eines Fingerabdruckes - schliesslich muss sie nur dokumentweit eindeutig sein.
Szenarien, in denen man Formatierungen für zwei unterschiedliche Elemente mit der ID foo in einem Stylesheet unterbringen will, sind nicht realitätsfern.
MfG ChrisB
ich vertraue dem folgenden Mozilla Artikel: https://developer.mozilla.org/en/Writing_Efficient_CSS
Dort steht drin, dass CSS-Selektoren von rechts nach links abgearbeitet werden. dh. bei div#foo wird erst nach dem Element mit der ID foo gesucht und dann überprüft, ob es ein div ist. Da IDs per Definition einzigartig sind, reicht #foo vollkommen aus.
Klingt schlüssig - also sollte #foo schneller sein als div#foo
Wie jQuery bzw Sizzle das händelt ist mir leider unbekannt. Allerdings würde ich auch hier sagen, weniger ist mehr.
In jQuery sind Selektoren schneller wenn man man das Element vorne dranhängt - div#foo ist schneller als #foo) - dazu gibts massenhaft Benchmarks im netz.
Zu guter Letzt ist div#foo schlechter Stil.
Das ist mir klar - nur in puncto jQuery trifft das eben nicht zu - angenommen ich habe folgendes:
<div id="content">
<div id="foo">
</div>
<div id="sidebar">
</div>
Dann ist jQuery mit dem Selektor div#content>div#foo wesentlich schneller als mit #foo.
Hi,
In jQuery sind Selektoren schneller wenn man man das Element vorne dranhängt - div#foo ist schneller als #foo) - dazu gibts massenhaft Benchmarks im netz.
Das wird an der Art und Weise liegen, wie dessen Selektor-Engine das DOM traversiert, um Elemente zu finden.
Zu guter Letzt ist div#foo schlechter Stil.
Das ist mir klar - nur in puncto jQuery trifft das eben nicht zu - angenommen ich habe folgendes:
<div id="content">
<div id="foo">
</div>
<div id="sidebar">
</div>
>
> Dann ist jQuery mit dem Selektor div#content>div#foo wesentlich schneller als mit #foo.
In allen Fällen? Oder nur in denen, in denen es div#content nicht gibt, und so eine weitere Suche nach div#foo entfällt? Wenn man Performance betrachten will, muss man sich sowohl die positiven als auch die negativen Fälle detailiert anschauen.
"Wesentlich am schnellsten" wäre "man" vermutlich mit getElementById, ohne Bloat-Framework-Script.
MfG ChrisB
--
Light travels faster than sound - that's why most people appear bright until you hear them speak.
Hi,
"Wesentlich am schnellsten" wäre "man" vermutlich mit getElementById, ohne Bloat-Framework-Script.
Das bringt mich auf eine bescheuerte Idee. Man könnte mal testen was schneller ist:
$("#foo") vs. $("div#foo") vs. $(document.getElementById('foo'))
Wobei, dann könnte man eigentlich auch gleich auf jQuery verzichten.
MfG Hase
Wobei, dann könnte man eigentlich auch gleich auf jQuery verzichten.
Wenn man jedes zu manipulierende ELement per ID ansprechen kann, braucht man vermutlich die Selektor-Engine des Frameworks nicht, richtig. Aber diese Frameworks stellen ja neben der Selektor-Engine noch mehr zur Verfügung.
$('#foo') mehrfach ausgeführt ist mit Sicherheit schneller als document.getElementById('foo') mehrfach ausgeführt.
Sizzle speichert bereits benutzte Elementreferenzen - bzw hänigt irgendwelche Attribute an die betreffenden Elemente. Das erspart das manuelle speichern von Elementrefernzen (obowohl das dennoch schneller wäre). Leider find' ich den Artikel grade nicht, den ich da letztens gelesen habe.
Hi,
Wenn man jedes zu manipulierende ELement per ID ansprechen kann, braucht man vermutlich die Selektor-Engine des Frameworks nicht, richtig. Aber diese Frameworks stellen ja neben der Selektor-Engine noch mehr zur Verfügung.
Eben. Deshalb lohnt sich die Betrachtung solcher "Sonderfälle" wie dem hier:
$('#foo') mehrfach ausgeführt ist mit Sicherheit schneller als document.getElementById('foo') mehrfach ausgeführt.
vermutlich gar nicht.
Interessant wird's erst bei komplizierteren Selektionen, wie bspw. an den Haaren herbeigezogen dem Auswählen aller A-Elemente, die keine Bilder enthalten, und sich in P-Elementen mit der Klasse "burps" befinden.
Auch das krieg ich per getElementsByTagName, className und childNodes in Kombination mit Schleifen sicher selber hin - aber zum einen ist es mühselig, das immer wieder in dieser epischen Breite hinzuschreiben, wenn mir das Framework eine Möglichkeit bietet, mit einem Aufruf etwas mit allen in der Selektion liegenden Elementen zu machen; und zum anderen verwenden die Frameworks eben daraufhin stark optimierte Algorithmen zum Auffinden dieser Elemente, die deutlich schneller sein dürften, als von mir mal schnell dahin geschriebenes, welches einem performance-tuning zu unterziehen ich auch nicht immer die Zeit oder Lust habe.
MfG ChrisB
Hi,
Kürzlich hab' ich irgendwo ein Benchmark zur Geschwindigkeit von JavaScript-Selektor-Engines gesehen. Die meisten Engines arbeiten deutlich schneller wenn man man anstatt #foo z.B. div#foo im Selektor notiert auf jQuery trifft das besonders zu).
Nun die Frage: ist das auch für CSS selbst relevant - sprich ist der Browser schneller wenn er div#foo selektiert oder doch lieber *[id=foo].
Beide Tätigkeiten (Selektion eines Elements per JS-Selektor-Engine und Ermittlung, welche CSS-Selektoren auf ein Element zutreffen), erfordern Traversing des DOM, und das je nach Selektor in teilweise sehr umfangreicher Form.
Bei der Anwendung von CSS dürfte es zwar generell performanter geschehen - weil es im Browser nativ implementiert ist, und nicht erst eine "Zwischenschicht" eingezogen ist, wie bei einer JS-Selektor-Engine.
Aber prinzipiell dürften in beiden Fällen die gleichen Überlegungen Gültigkeit besitzen.
Natürlich ist dieses Beispiel sehr theoretisch - aber wie siehts mit banaleren dingen aus: div.foo vs. .foo vs. div#foo vs. #foo - wobei das Element nur 1x vorkommt.
Das ist in der Tat sehr theoretisch, und ohne Benchmarks für einzelne Testszenarien auch schwer eindeutig zu beantworten.
Google Page Speed hat jedoch unter "Optimize browser rendering" auch den Tipp, Use efficient CSS selectors - kannst du dir ja mal anschauen, und dir selber eine Meinung drüber bilden.
MfG ChrisB
Google Page Speed hat jedoch unter "Optimize browser rendering" auch den Tipp, Use efficient CSS selectors - kannst du dir ja mal anschauen, und dir selber eine Meinung drüber bilden.
Der ist hart :)
For example, if you need two different styles for an ordered list item and an ordered list item, instead of using two rules:
ul li {color: blue;}
ol li {color: red;}
You could encode the styles into two class names and use those in your rules; e.g:
.unordered-list-item {color: blue;}
.ordered-list-item {color: red;}
Als ich das gelesen hab', ist mir nur noch "wtf" durch den Kopf gegangen :)
Dass ein Klassen-Selektor schneller ist als der Nachfahren-Selektor kann durchaus sein, das HTML dafür unsinnig aufblähen und Redundanzen einbauen kanns auch nicht sein.
Hi,
Der ist hart :)
For example, if you need two different styles for an ordered list item and an ordered list item, instead of using two rules:
ordered vs. unordered dürften die hier wohl meinen.
You could encode the styles into two class names and use those in your rules; e.g:
.unordered-list-item {color: blue;}
.ordered-list-item {color: red;}
>
> Als ich das gelesen hab', ist mir nur noch "wtf" durch den Kopf gegangen :)
Ich schrieb ja, eigene Meinung dazu bilden - alles blind für bare Münze und in allen Situationen optimalste Lösung zu betrachten, würde ich nicht empfehlen.
> Dass ein Klassen-Selektor schneller ist als der Nachfahren-Selektor kann durchaus sein, das HTML dafür unsinnig aufblähen und Redundanzen einbauen kanns auch nicht sein.
Kommt sicher auf den Einzelfall an - Umfang des Dokumentes, Quantität des Auftretens darüber zur formatierender Elemente, Verschachtelungstiefe, etc. - mag also durchaus sein, dass das in bestimmten Fällen die Performance des Renderings verbessern kann; aber pauschal würde ich das auch nicht für sinnvoll halten.
MfG ChrisB
--
Light travels faster than sound - that's why most people appear bright until you hear them speak.
@@suit:
nuqneH
ul li {color: blue;}
ol li {color: red;}
>
> You could encode the styles into two class names and use those in your rules; e.g:
>
> ~~~css
.unordered-list-item {color: blue;}
> .ordered-list-item {color: red;}
Als ich das gelesen hab', ist mir nur noch "wtf" durch den Kopf gegangen :)
Das Beispiel ist auch völlig sinnfrei gewählt. Da in 'ul'/'ol' nicht anderes als 'li'-Elemente enthalten sind, ist der Nachfahrenselektor hier überflüssig; man die Farbe gleich für die Liste angeben:
ul {color: blue;}
ol {color: red;}
Qapla'