Geschwindigkeit von in Funktion gekapseltem Code in Firefox
Simplex
- javascript
Hi,
mir ist da etwas aufgefallen, als ich ein Skript im Firefox (3.5/Win) getestet habe. Mein Code von folgender Form
function doSomething()
{
//zeitintensive Operationen; z.B:
for(var k=0; k<30; k++)
{
foo.push(bar);
foo=(foo.join(",")+bar+","+bar).split(",");
}
}
for(var i=0; i<500; i++)
doSomething();
läuft spürbar langsamer als selbiger Code umgeschrieben zu:
var foo=[], bar="a";
for(var i=0; i<500; i++)
{
//zeitintensive Operationen; z.B:
for(var k=0; k<30; k++)
{
foo.push(bar);
foo=(foo.join(",")+bar+","+bar).split(",");
}
}
Die Geschwindigkeitseinbußen scheinen mit dem Umstand zusammenzuhängen, dass die „zeitintensiven Operationen“ innerhalb einer Funktion stehen. (bei obigem Code hält sich der Geschwindigkeitsunterschied noch sehr in Grenzen; bei meinem tatsächlichen – deutlich längeren – Code beträgt der Unterschied fast den Faktor 2)
Alles, was ich wissen wollte, ist: Hätte ich damit rechnen müssen, dass sich durch die Funktionsaufrufe die Laufzeit so sehr verschlechtert (oder kann ich der SpiderMonkey/TraceMonkey-Engine die Schuld dafür in die Schuhe schieben ;-) ?
läuft spürbar langsamer als selbiger Code umgeschrieben zu:
Kann ich nicht nachvollziehen. Im Gegenteil der erste Code ist um einiges schneller.
Struppi.
Kann ich nicht nachvollziehen. Im Gegenteil der erste Code ist um einiges schneller.
Okay, vielen Dank für die Rückmeldung.
Ich werde mir die Sache dann nochmal auf einem anderen Rechner ansehen und ein wenig „weiterforschen“.
Gruß,
Simplex
Hi,
läuft spürbar langsamer als selbiger Code umgeschrieben zu:
Kann ich nicht nachvollziehen. Im Gegenteil der erste Code ist um einiges schneller.
Von der Logik her würde ich aber sagen, dass der erste Code langsamer sein sollte, weil ja der gleiche Code ausgeführt wird, nur noch mit Zusätzlichen Funktionsaufrufen (Abspeichern und Auslesen der Rücksprungadresse).
Waren die Variablen foo und bar bei beiden Versuchen global definiert? Ansonsten kann es auch sein, dass der grosse Zeitunterschied beim OP was damit zu tun hat, dass die Variablen in der Funktion immer wieder neu angelegt werden, weil sie ja nur solange leben, bis die Funktion durchgelaufen ist.
mfG,
steckl
Von der Logik her würde ich aber sagen, dass der erste Code langsamer sein sollte, weil ja der gleiche Code ausgeführt wird, nur noch mit Zusätzlichen Funktionsaufrufen (Abspeichern und Auslesen der Rücksprungadresse).
var count = 50;
function doSomething() {
//zeitintensive Operationen; z.B:
for(var k = 0; k < 30; k++) {
foo.push(bar);
foo=(foo.join(",")+bar+","+bar).split(",");
}
}
var foo=[], bar="a";
var t1 = new Date();
for(var i = 0; i < count; i++) doSomething();
var t2 = new Date();
var foo=[], bar="a";
var t3 = new Date();
for(var i = 0; i < count; i++) {
//zeitintensive Operationen; z.B:
for(var k = 0; k < 30; k++) {
foo.push(bar);
foo=(foo.join(",")+bar+","+bar).split(",");
}
}
var t4 = new Date();
alert(
'function: '+(t2 - t1)
+ '\nloop: '+(t4 - t3)
)
Bei mir (Fx 3.5) schwankt das je nach Tageszeit ;-)
Gestern war function deutlich schneller, jetzt ist es etwas langsamer. Auf jeden Fall kein deutlicher Unterschied.
Waren die Variablen foo und bar bei beiden Versuchen global definiert? Ansonsten kann es auch sein, dass der grosse Zeitunterschied beim OP was damit zu tun hat, dass die Variablen in der Funktion immer wieder neu angelegt werden, weil sie ja nur solange leben, bis die Funktion durchgelaufen ist.
Dann leg mal die Variabeln lokal an und du wirst erstaunt sein.
Struppi.
Dann leg mal die Variabeln lokal an und du wirst erstaunt sein.
Unsinn, ich erzähle Mist. Es gibt keinen Unterschied in der Laufzeit.
Struppi.
Hi,
Dann leg mal die Variabeln lokal an und du wirst erstaunt sein.
Unsinn, ich erzähle Mist. Es gibt keinen Unterschied in der Laufzeit.
Bei einer so geringen Anzahl von Aufrufen spielt das wohl eh keine Rolle und ich weiss auch nicht, ob es bei JS genauso ist, aber in anderen Programmiersprachen werden lokale Variablen (wenn sie nicht static sind) bei jedem Funktionsaufruf neu auf dem Stack gelegt, waehrend globale Variablen nur einmal zu Beginn des Programms auf dem Heap abgelegt werden.
Darum sollte bei vielen Aufrufen die Durchlaufzeit mit globalen Variablen geringer sein, wenn ich mich nicht voellig irre.
mfG,
steckl
Hallo steckl
… werden lokale Variablen (wenn sie nicht static sind) bei jedem Funktionsaufruf neu auf dem Stack gelegt, waehrend globale Variablen nur einmal zu Beginn des Programms auf dem Heap abgelegt werden.
Und das ist _so_ zeitaufwändig?
Auf dem Stack werden nicht nur lokale Variablen abgelegt, dort werden auch die Prozessorregister und die Rücksprungadresse gesichert (und das nicht nur bei selbst definierten Funktionen, sondern auch bei denen, die die Programmiersprache selbst mitbringt). Anlegen der Variablen auf dem Stack bedeutet doch nur, dass dort der nötige Platz reserviert wird, also beim anpassen des Stackpointers berücksichtigt wird.
Und lesen oder beschreiben von Variablen auf dem Stack dauert mit Sicherheit nicht länger als wo anders.
Auf Wiederlesen
Detlef
Hi,
Und das ist _so_ zeitaufwändig?
Nein, vor allem nicht bei 50 Aufrufen.
Auf dem Stack werden nicht nur lokale Variablen abgelegt, dort werden auch die Prozessorregister und die Rücksprungadresse gesichert (und das nicht nur bei selbst definierten Funktionen, sondern auch bei denen, die die Programmiersprache selbst mitbringt). Anlegen der Variablen auf dem Stack bedeutet doch nur, dass dort der nötige Platz reserviert wird, also beim anpassen des Stackpointers berücksichtigt wird.
Und lesen oder beschreiben von Variablen auf dem Stack dauert mit Sicherheit nicht länger als wo anders.
Ich meinte nur, dass es schneller gehen sollte, wenn die Variable nur einmal angelegt wird und nicht jedes mal neu. Dass der Unterschied gross ist glaube ich aber auch nicht.
mfG,
steckl