Autor Beitrag
Gausi
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 8548
Erhaltene Danke: 477

Windows 7, Windows 10
D7 PE, Delphi XE3 Prof, Delphi 10.3 CE
BeitragVerfasst: Di 08.02.05 11:39 
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:
ausblenden 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;  // Geschwindigkeit, mit der die Items fallen
    Bild:=TImage.Create(Form1);
    Bild.Parent:=Form1.MainPanel;
    case Random(100of
        // verschiedene Fälle, die alle prinzipiell gelich aussehen
        [...]
        else begin
            // Grafiken sind in Ressourcen eingebunden
            resStream:= TResourceStream.CreateFromID(HInstance, 200, RT_RCDATA);
            PWert:=100;  // Punkte fürs anklicken
            LWert:=0// "Leben"
        end;
    end;
    Bild.Picture.Bitmap.LoadFromStream(ResStream);
    resStream.Free;
    Bild.Left:=random(Form1.MainPanel.Width-120); // horizontale Position zufällig
    Bild.OnMouseDown:=Form1.IMAGEMouseDown;
    //[...] ein paar weitere Eigenschaften werden noch gesetzt
end;


Das Erzeugen hab ich zu Testzwecken ins OnIdle-Event gepackt
ausblenden 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) < 5then
    begin
        //Item erzeugen und in eine Liste packen
        Bierflasche:=TBierflasche.create;
        FlaschenListe.Add(Bierflasche);
    end;
    // Alle Items überprüfen
    for i:=FlaschenListe.Count-1 downto 0 do
    begin
        Bierflasche:=FlaschenListe[i] as TBierflasche;
        if Bierflasche.Bild.Top<200 then
        // weiter runterfallen lassen
            Bierflasche.Bild.Top:=Bierflasche.Bild.Top + Bierflasche.Speed
        else
        begin
            if Bierflasche.PWert>=0 then
            begin
                dec(Leben);
                [...]
            end;
            // Item entfernen
            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?

_________________
We are, we were and will not be.
AXMD
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 4006
Erhaltene Danke: 7

Windows 10 64 bit
C# (Visual Studio 2019 Express)
BeitragVerfasst: Di 08.02.05 11:44 
Sieht stark danach aus, als würdest du irgendetwas nicht freigeben... tippe stark auf

ausblenden Delphi-Quelltext
1:
Bierflasche:=TBierflasche.create;					
(zweites Codeschnipsel)

AXMD
Gausi Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 8548
Erhaltene Danke: 477

Windows 7, Windows 10
D7 PE, Delphi XE3 Prof, Delphi 10.3 CE
BeitragVerfasst: 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!

_________________
We are, we were and will not be.
Tino
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Veteran
Beiträge: 9839
Erhaltene Danke: 45

Windows 8.1
Delphi XE4
BeitragVerfasst: Di 08.02.05 12:10 
...und im Destruktor von TBierflasche nicht vergessen die Variable Bild freizugeben.
Gausi Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 8548
Erhaltene Danke: 477

Windows 7, Windows 10
D7 PE, Delphi XE3 Prof, Delphi 10.3 CE
BeitragVerfasst: Di 08.02.05 12:13 
Das hatte ich schon:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
destructor TBierflasche.destroy;
begin
    Bild.Free;
    inherited destroy;
end;
Trotzdem danke!

_________________
We are, we were and will not be.
MitschL
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 211

Win 98 SE, Win 2000
D5 Pers, D6 Pers und D7 Pro
BeitragVerfasst: 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!

_________________
"Bloßes Ignorieren ist noch keine Toleranz." (Theodor Fontane)
Udontknow
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2596

Win7
D2006 WIN32, .NET (C#)
BeitragVerfasst: Di 08.02.05 13:43 
Poste doch bitte mal die Klassendeklaration.

Cu,
Udontknow
Gausi Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 8548
Erhaltene Danke: 477

Windows 7, Windows 10
D7 PE, Delphi XE3 Prof, Delphi 10.3 CE
BeitragVerfasst: Di 08.02.05 14:18 
Da ist eigentlich nichts besonderes bei:
ausblenden 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.

_________________
We are, we were and will not be.
Udontknow
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2596

Win7
D2006 WIN32, .NET (C#)
BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2596

Win7
D2006 WIN32, .NET (C#)
BeitragVerfasst: Mi 09.02.05 16:54 
Woran hat´s denn nun gelegen?

Cu,
Udontknow
Gausi Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 8548
Erhaltene Danke: 477

Windows 7, Windows 10
D7 PE, Delphi XE3 Prof, Delphi 10.3 CE
BeitragVerfasst: 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.

_________________
We are, we were and will not be.