Entwickler-Ecke
Sonstiges (Delphi) - Wieso wird das immer langsamer?
Gausi - Di 08.02.05 11:39
Titel: Wieso wird das immer langsamer?
Ich schreibe grad ein kleines Spielchen, bei dem von oben Sachen runterfallen, die man im Fallen anklicken muss.
Die "Sachen" sind im Wesentlichen TImages, die aber weitere Eigenschaften wie z.B. Geschwindigkeit haben. Der Konstruktor sieht so aus:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23:
| constructor TBierflasche.create; var resStream: Tresourcestream; begin inherited; Speed:= 3; Bild:=TImage.Create(Form1); Bild.Parent:=Form1.MainPanel; case Random(100) of [...] else begin resStream:= TResourceStream.CreateFromID(HInstance, 200, RT_RCDATA); PWert:=100; LWert:=0; end; end; Bild.Picture.Bitmap.LoadFromStream(ResStream); resStream.Free; Bild.Left:=random(Form1.MainPanel.Width-120); Bild.OnMouseDown:=Form1.IMAGEMouseDown; end; |
Das Erzeugen hab ich zu Testzwecken ins OnIdle-Event gepackt
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25:
| if (random(100) < 5) then begin Bierflasche:=TBierflasche.create; FlaschenListe.Add(Bierflasche); end; for i:=FlaschenListe.Count-1 downto 0 do begin Bierflasche:=FlaschenListe[i] as TBierflasche; if Bierflasche.Bild.Top<200 then Bierflasche.Bild.Top:=Bierflasche.Bild.Top + Bierflasche.Speed else begin if Bierflasche.PWert>=0 then begin dec(Leben); [...] end; Bierflasche.Bild.Picture.Assign(Nil); FlaschenListe.Delete(i); end; end; |
Dieses Stück Code wird also ständig wiederholt. In 5% (random(100)<5) der Fälle wird ein neues Item erzeugt, und wenn es unten angekommen ist, wird es wieder entfernt.
Problem ist: Das wird immer langsamer. Am Anfang flutschen die Bilder richtig flott von oben nach unten, aber nach einiger Zeit....ne.
Die Anzahl der Items bleibt konstant ungefähr bei 10, die Speicherauslastung bleibt laut Taskmanager bei etwa 4.5MB.
Jemand ne Idee, warum die Geschwindigkeit im während der Programmlaufzeit so extrem abnimmt?
AXMD - Di 08.02.05 11:44
Sieht stark danach aus, als würdest du irgendetwas nicht freigeben... tippe stark auf
Delphi-Quelltext
1:
| Bierflasche:=TBierflasche.create; |
(zweites Codeschnipsel)
AXMD
Gausi - Di 08.02.05 12:06
Aargghhhh... Hatte zwar den Destructor geschrieben, aber der wurde nicht richtig aufgerufen, weil ich override vergessen hatte.. :autsch:
Jetzt scheint alles in Ordnung zu sein, danke!
Tino - Di 08.02.05 12:10
...und im Destruktor von TBierflasche nicht vergessen die Variable Bild freizugeben.
Gausi - Di 08.02.05 12:13
Das hatte ich schon:
Delphi-Quelltext
1: 2: 3: 4: 5:
| destructor TBierflasche.destroy; begin Bild.Free; inherited destroy; end; |
Trotzdem danke!
MitschL - Di 08.02.05 13:18
Ähm,
irgendwie bleibt mir bei den Auswirkungen der Sinn verborgen. Wenn ich etwas nicht freigebe, dann steigt mein Speicherbedarf im Laufe der Programmarbeit (so eigene Erfahrungen), was dazu führen kann, daß das Programm u.U. langsamer läuft.
Nun bleibt aber das Programm hier wohl gleich groß und trotzdem wird es langsamer, weil wegen nicht destruierten Bierflaschen? :gruebel:
Kann mir das mal einer näher bringen?
gegrüßt!
Udontknow - Di 08.02.05 13:43
Poste doch bitte mal die Klassendeklaration.
Cu,
Udontknow
Gausi - Di 08.02.05 14:18
Da ist eigentlich nichts besonderes bei:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8:
| TBierFlasche = class(TObject) Bild:Timage; Speed:integer; PWert:integer; LWert:integer; constructor create; destructor destroy; override; end; |
Warum das jetzt besser klappt, weiss ich auch nicht genau. Fakt ist, dass ohne das 'override' der Destructor bei
FlaschenListe.delete(i) nicht aufgerufen wird. Außerdem reagieren dann einige 'Flaschen' nicht auf OnMouseDown, oder erst dann, wenn man eine andere vorher wegklickt.
Udontknow - Di 08.02.05 14:47
Es hätte ja sein können, das "Bild" eine globale Variable wäre... :wink:
So sehe ich erst mal auch nichts. Aber was Optimierung angeht: Wieso ziehst du immer wieder für jede Instanz das Bitmap als Resource? Wäre es nicht effektiver, einmal bei Start eine Bitmapliste zu erstellen und einfach dann das Bitmap über einen Index zu referenzieren und auf die Komponente zu zeichnen, anstelle für jede TBierflasche-Instanz ein Bitmap im Speicher zu halten?
Cu,
Udontknow
Udontknow - Mi 09.02.05 16:54
Woran hat´s denn nun gelegen?
Cu,
Udontknow
Gausi - Mi 09.02.05 17:10
Keine Ahnung. Behoben wurde das Problem auf jeden Fall durch 'Override' des Destructors. Zu deinem Vorschlag: Das tut sich nicht viel. Die Bitmaps sind ziemlich klein (90x90), ich habe ca. 7 verschiedene Grafiken, und so gut wie nie mehr als 15 Flaschen gleichzeitig erzeugt. Da ist die Speicherersparnis nicht so riesig, als dass sich der Aufwand des Umcodens für dieses kleine Spielchen lohnen würde.
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2025 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!