Hallo,
jetzt habe ich Gelegenheit zum nachmessen...
Ich traue deinem Vergleich kein bisschen. Eine Schleife, die 1000× dasselbe tut – das sollte die JavaScript-Engine wegoptimieren.
Das lässt sich ebenfalls messen.
Hier mein Test:
let i=0;
for (i=1; i<=100; i++) {
let ii = i.toString().padStart(3, '0');
$("body").append("<fieldset id='fs"+ii+"'><label>Input "+ii+"-1<input type='radio' name='rb"+ii+"' value='11'><label>Input "+ii+"-2<input type='radio' name='rb"+ii+"' value='22'><label>Input "+ii+"-3<input type='radio' name='rb"+ii+"' value='33' checked><label>Input "+ii+"-4<input type='radio' name='rb"+ii+"' value='44'></fieldset>")
}
let v1,v2,v3,v4, max=100;
console.time("Empty Loop");
for (i=1; i<max; i++) {
}
console.timeEnd("Empty Loop");
console.time("jQuery :radio");
for (i=1; i<max; i++) {
v1 = $(":radio[name='rb099']:checked").val();
}
console.timeEnd("jQuery :radio");
console.time("jQuery [type=radio]");
for (i=1; i<max; i++) {
v2 = $("[type=radio][name='rb099']:checked").val();
}
console.timeEnd("jQuery [type=radio]");
console.time("native");
for (i=1; i<max; i++) {
let s = document.querySelector("[type=radio][name='rb099']:checked");
v3 = s.value;
}
console.timeEnd("native");
console.time("nativeAll");
for (i=1; i<max; i++) {
let s = document.querySelectorAll("[type=radio][name='rb099']:checked");
v4 = s[0].value;
}
console.timeEnd("nativeAll");
console.log("jq1: " + v1 + ", jq2: " + v1 + ", na1:" + v3 + ", na2:" + v4);
Ausgabe mit max=100:
Empty Loop: 0.01318359375ms
jQuery :radio: 138.073974609375ms
jQuery [type=radio]: 18.42822265625ms
native: 13.638916015625ms
nativeAll: 9.412841796875ms
jq1: 33, jq2: 33, na1:33, na2:33
Ausgabe mit max=1000:
Empty Loop: 0.03173828125ms
jQuery :radio: 658.901123046875ms
jQuery [type=radio]: 107.217041015625ms
native: 92.0048828125ms
nativeAll: 84.259033203125ms
jq1: 33, jq2: 33, na1:33, na2:33
Gemessen mit Chrome 63 unter Windows 7, auf einer virtuellen Maschine unbekannter Leistungsfähigkeit. Die Zeiten können also auch je nach Host-Belastung etwas schwanken.
Man erkennt, dass V8 die Schleifen nicht wegoptimiert. Aber man erkennt auch, dass die Messung sehr unscharf ist, die Zahlen verhalten sich nicht 1:10 für 100 und 1000 Durchläufe. Ich muss das nochmal auf einer nichtvirtuellen Maschine wiederholen, habe ich gerade nicht zur Hand.
Die Erkenntnis ist aber: :radio ist deutlich langsamer als [type=radio], und [type=radio] ist in jQuery unwesentlich langsamer als querySelector.
Merkwürdig finde ich nur, dass querySelectorAll konsistent 10% schneller ist als querySelector. Da ich einen Radio-Button ganz am Ende suche, sollten die beiden in etwa gleich schnell sein.
Das ändert sich, wenn ich rb019 suche, dann bekomme ich bei max=1000 diese Werte:
Empty Loop: 0.032958984375ms
jQuery :radio: 630.801025390625ms
jQuery [type=radio]: 108.5830078125ms
native: 18.47314453125ms
nativeAll: 76.590576171875ms
jq1: 33, jq2: 33, na1:33, na2:33
D.h. querySelector ist im Mittel schneller als querySelectorAll, weil es einfach nach dem 1. Treffer aufhört.
Tjaaa, und der hier
console.time("qid");
for (i=1; i<max; i++) {
v5 = $("#fs099 input[name=rb099]:checked").val();
}
console.timeEnd("qid");
console.time("nid");
for (i=1; i<max; i++) {
v6 = document.getElementById("fs099").querySelector("[type=radio]:checked").value;
}
console.timeEnd("nid");
läuft natürlich viel schneller durch 😀. Mit max=1000 die jQuery-Variante in 19ms, die native-Variante in 1,5ms. Hier macht sich der jQuery-Initialaufwand massiv bemerkbar. D.h. die beste Peephole-Optimierung nützt nichts, wenn man den falschen Algorithmus hat. Aber das wussten wir ja schon vorher. Allerdings ist auch document.querySelector("#fs099 [type=radio][name='rb099']:checked")
nur minimal langsamer (1,7ms vs 1,5ms) als die nid Version. Die Trennung lohnt also nicht.
Und dass die GANZE Nummer nicht lohnt, wenn man nur einen Radiobutton sucht, ist auch offenkundig. Es wird nur ganz wenige Seiten geben, auf denen sich der Unterschied spürbar bemerkbar macht.
Rolf
sumpsi - posui - clusi