![]() |
Re: Performanceproblem mit ca. 30000 Listboxeinträgen
TListBox.Items[] hat zwar den Datentyp TStrings, ist aber nicht von TStringList abgeleitet
sondern gehört zur Klasse TListBoxStrings !!! Hier ein kleiner Ausschnitt aus Unit StdCtrls:
Delphi-Quellcode:
Die Methoden Get und Put sind um Welten langsamer als TStringList.Get/Put.
TListBoxStrings = class(TStrings)
private ListBox: TCustomListBox; protected procedure Put(Index: Integer; const S: string); override; function Get(Index: Integer): string; override; Da nutzt auch BeginUpdate nicht viel!! Also geht der WorkAround so: Alle Items auf ein TStringList-Objekt kopieren, auf dieser StringListe arbeiten und am Ende zurückkopieren.
Delphi-Quellcode:
liste := TStringList.Create;
liste.Assign(ListBox1.Items); // auf Liste arbeiten .... // und zurück ListBox1.Items := liste; liste.Free; |
Re: Performanceproblem mit ca. 30000 Listboxeinträgen
Liste der Anhänge anzeigen (Anzahl: 1)
@Sharky
Ich habe deinen Quelltext eigentlich nur reinkopiert und den rest gelöscht. und ich bleibe dabei das jetzte Beispiel1 Programm ist auf keine Fall schneller als Programm Beispiel
Delphi-Quellcode:
[edit=sakura] Doppelpost gelöscht. Mfg, sakura[/edit]
procedure TForm1.Addmyitem(const AItem: string; const AColor: TColor);
var x, i,pl0 : Integer; counte : array[0..409] of Integer; begin Anzeige.Items.InsertObject(0, AItem, TObject(AColor)); DoubleBuffered := True; // Alle "Counter" auf 0 setzen for i := 0 to 409 do begin Counte[i] := 0; end; // Hier beginnen die Berechnungen for pl0 := Form1.Anzeige.count - 1 downto 0 do // (1) Das ist die Schleife für die Items (30.000) begin for x := 0 to 409 do // (2) Das ist die Schleife für die Berechnung begin if StrToInt(Form1.Anzeige.Items[pl0]) in werte[x] then Counte[x] := 0 else Inc(Counte[x]); end; // (2) Hier endet die Schleife für die Berechnung for x := 0 to 409 do // (3) Das ist die Schleife für die Ausgabe begin (FindComponent('Label' + IntToStr(x + 2)) as TLabel).Caption := IntToStr(Counte[x]); end; // (3) Hier endet die Schleife für die Ausgabe end; // (1) hier endet die Schleife für die Items. end; |
Re: Performanceproblem mit ca. 30000 Listboxeinträgen
Zitat:
Danke Dir, aber dies werde ich im Moment nicht nachgehen, da meine labels meisents mit nil angesprochen weerden im längeren Programm, hab sie hier nur veranschaulichung alle mitzählen lassen. :cyclops: |
Re: Performanceproblem mit ca. 30000 Listboxeinträgen
?? in deiner doppeltgeposteten zip verwendest du doch deinen originalcode .. nicht Sharky's ... wenn ich das recht sehe ... hmm :gruebel: (den haste ja auch mitgepostet) ...
|
Re: Performanceproblem mit ca. 30000 Listboxeinträgen
Delphi-Quellcode:
Du brauchst deine 410 Labels (was ja auch schon Wahnsinn ist) nicht 30000 Mal beschicken.
for pl0 := Form1.Anzeige.count - 1 downto 0 do // (1) Das ist die Schleife für die Items (30.000)
begin (* * * du bist auch ein "Held", wenn du 410 Mal auf die gleichen Daten zugreifst !!!! * *) // den Wert AUSSERHALB der inneren Schleife lesen // und auch gleich als Integer merken (spart 409 *30000 Aufrufe auf StrToInt !!!) aktwert := StrToInt(Form1.Anzeige.Items[pl0]); for x := 0 to 409 do // (2) Das ist die Schleife für die Berechnung begin if aktwert in werte[x] then Counte[x] := 0 else Inc(Counte[x]); end; Es würde reichen, nur jedes 100. Mal die Labels zu aktualisieren:
Delphi-Quellcode:
if ((pl1 mod 100) = 0) then
for x := 0 to 409 do // (3) Das ist die Schleife für die Ausgabe begin (FindComponent('Label' + IntToStr(x + 2)) as TLabel).Caption := IntToStr(Counte[x]); end; |
Re: Performanceproblem mit ca. 30000 Listboxeinträgen
Zitat:
Ich habs leider schon gelöscht, ich hatte schon mal dieses Programm auf
Delphi-Quellcode:
............
meineliste := TStringList.Create;
Da hatte ich die Listbox nur och zur Anzeige benutzt und die Komplette Berechnung auf meineListe umgestellt hatte aber nicht wirklich was gebracht. |
Re: Performanceproblem mit ca. 30000 Listboxeinträgen
Hallo Thomas,
du hast da ein Problem, das du unbedingt mit Delphi lösen möchtest. Dass du mit Delphi noch ein wenig auf dem Kriegsfuß stehst, ist verzeihlich. Dass du aber nicht in der Lage bist, nachdem du nun bereits ein Dutzend threads zum Thema eröffnet hast, dein Problem mit einer halben Seite Text so zu beschreiben, dass es von den Nothelfern in diesem Forum halbwegs verstanden werden kann, stimmt mich nachdenklich. Das Problem hast du dir ja wohl nicht selbst ausgedacht - du erwähntest Vergleiche mit anderen, die du angestellt hast. Ist die eigentliche Aufgabenstellung vielleicht von jemandem formuliert worden, der die Fähigkeit besitzt, sich klar und verständlich auszudrücken und sich bei seinen Ausführungen auf das Wesentliche zu konzentrieren? Kannst du nicht einfach einen Link auf die Aufgabenstellung posten? Wenn nicht, kannst du dann wenigstens sagen, warum nicht? Grüße vom marabu |
Re: Performanceproblem mit ca. 30000 Listboxeinträgen
in solchen Fällen führe ich immer eine Zeitmessung der einelnen Schleifen durch !
Damit wird schnell klar wo die meiste Zeit verbraten wird ....
Delphi-Quellcode:
Ergibt bei mir beim 1. mal 157ms ... alle andern funktionen liegen bei 0ms !!
istart:=GetTickCount;
for x := 0 to 409 do begin (FindComponent('Label' + IntToStr(x + 1)) as TLabel).Caption :=IntToStr(Counte[x]); end; ShowMessage(IntToStr(GetTickCount-istart)); Das Problem ist aber nicht die inttostr Anweisung, sondern die Wertzuweisung an die Labels. Die Lösung besteht darin das die Eigenschaft AutoSize der gesamten Labels auf False gesetz werden muss !!! :warn: Ergebnis der Messung dannach : 16ms Also ein gutes 10tel der Zeit ! |
Re: Performanceproblem mit ca. 30000 Listboxeinträgen
oops ... das mit dem Datei öffnen hatte ich ja glatt übersehen :wall:
so .. hier aber jetzt die Lösung des Problems .... :-D Der Trick ist ... das man die Werte der Listbox extra nach int Konvertiert .. s. Unten !
Delphi-Quellcode:
{-----------------------------------------------------------------------------
Procedure: Addmyitem Arguments: const AItem: string; const AColor: TColor Hier werden neue Einträge in die Listbox durchgeführt. Es werden auch die Berechnung der "Punkt" und deren Ausgabe erledigt. -----------------------------------------------------------------------------} procedure TForm1.Addmyitem(const AItem: string; const AColor: TColor); var x, i, y, Counter : Integer; cg, cb : double; counte : array[0..409] of Integer; //Dynamisches Integer Array iArray : array of integer; begin Anzeige.Items.InsertObject(0, AItem, TObject(AColor)); DoubleBuffered := True; cg := (Form2.SpinEdit1.Value); cb := (Form2.SpinEdit2.Value); //werte von Listbox Anzeige in Array of Integer konvertieren for i := 0 to Anzeige.Count - 1 do begin //Array vergrößern SetLength(iArray, i + 1); //String to Int wndeln iArray[i] := StrToInt(Anzeige.Items[i]); end; // Alle "Counter" auf 0 setzen Counter := 0; ZeroMemory(@Counte, SizeOf(counte)); // Hier beginnen die Berechnungen // Jedes Item der Listbox durchlaufen - Jetzt iArray for x := 0 to High(iArray) do begin if iArray[x] in [1, 3, 10] then Inc(Counter); if iArray[x] in [6] then Counter := 0; // Mit jedem SetOfByte vergleichen for y := 0 to 409 do begin //hier mit dem Int Array arbeiten if iArray[x] in werte[y] then Counte[y] := 0 else Inc(Counte[y]); end; end; // Ab hier kommt die Ausgabe der Berechnungen Label1.Caption := IntToStr(Counter); if counter = cg then begin Image2.Picture.Assign(bild2); // Bilid zuweisen label1.font.color := CLblack end else begin // Wass passiert wenn keiner von beiden werten zutrifft? // Dann könnte diese If-Abfrage nämlich weg. Entweder ist counter = cg // oder er ist es nicht. if counter = cb then begin Image2.Picture.Assign(bild1); label1.font.color := CLwhite; end; end; for x := 0 to 409 do begin (FindComponent('Label' + IntToStr(x + 1)) as TLabel).Caption := IntToStr(Counte[x]); end; //Array freigeben iArray := nil; end; |
Re: Performanceproblem mit ca. 30000 Listboxeinträgen
Zitat:
das kann/sollte man noch optimieren ;-) Zitat:
Wenn ein dynamisches Array vergrössert wird passiert folgendes:
Da man ja vor der Schleife weiss wie groß das Array sein muss sollte es also auch einmal auf diese größe gesetzt werdne.
Delphi-Quellcode:
Das dürfte noch einmal die Geschwindigkeit erhöhen.
//Arraygröße festlegen
SetLength(iArray, Anzeige.Count - 1); //werte von Listbox Anzeige in Array of Integer konvertieren for i := 0 to Anzeige.Count - 1 do begin //String to Int wndeln iArray[i] := StrToInt(Anzeige.Items[i]); end; |
Alle Zeitangaben in WEZ +1. Es ist jetzt 14:30 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz