![]() |
FOR oder WIHLE was ist schneller (Stringgrid befüllen)
Hallo zusammen,
kann mir jemand von euch sagen was schneller ist FOR oder WHILE Schleifen ich bin gerade dabei mein Programm zu optimieren. Dabei werden mehrere Schleifen durchlaufen und die aufbereiteten Ergebnisse dann in einem Sringgrid dargestellt. Momentan stoße ich dabei auf Performance Probleme, ich habe auch schon probiert eine BeginUpdate/EndUpdate einzubauen allerdings scheint das mit einem Stringgrid nicht so einfach zu funktionieren wie mit einer Treeview oder Listbox-Komponente alternativ dazu setzte ich den RowCount des Stringgrid jetzt erst zum Schluss nach der For-Schleife auf den richtigen Wert. |
Re: FOR oder WIHLE was ist schneller (Stringgrid befüllen)
For ist m.W als While-Schleife implementiert. es sollte dann eigentlich keinen Unterschied zwischen den beiden Varianten geben
|
Re: FOR oder WIHLE was ist schneller (Stringgrid befüllen)
Wenn du bereits vorher weist, wie oft die Schleife ausgeführt werden muss, ist die for-Schleife besser.
Wobei das im Endeffekt egal sein dürfe da iirc die for-Schleife intern in eine While-Schleife umgewandelt wird. Aber evtl. kann der Compiler dadurch noch etwas optimieren da die Zählervariable nicht verändert werden kann ... Aber wenn dich der Geschwindigkeitsunterschied interessiert, optimierst du wahrscheinlich an der falschen Stelle :gruebel: Um das Halbwissen perfekt zu machen:
Delphi-Quellcode:
wird zu
for i := 0 to 5 do
begin // ... end;
Delphi-Quellcode:
i := 5;
while(i <> 0) begin // ... dec(i); end; |
Re: FOR oder WIHLE was ist schneller (Stringgrid befüllen)
Hallo,
überleg erstmal ob du dir nicht die ein oder andere verschachtelte Schleife komplett sparen kannst, da hier der größte "Zeitverschleiß" auftritt... ansonsten kannste noch probieren, die Ergebnisse erst in ein Array zwischenzuspeichern und dann nach dem durchlaufen der Schleifen auszugeben... da das "auf den Bildschirm schreiben" länger dauert als man vermuten würde... Gruß Maxi |
Re: FOR oder WIHLE was ist schneller (Stringgrid befüllen)
@Te7Ris: ja dem Problem wollte ich schon aus dem Weg gehen indem ich den Row Count des Stinggrid erst nach der Schleife setze, allerdings bringt das kein Effekt, nach unnötige Verschachtelungen hab ich auch bereits gesucht allerdings ist da jetzt nicht mehr alt soviel rauszuholen.
|
Re: FOR oder WIHLE was ist schneller (Stringgrid befüllen)
Da das Befüllen eines Stringgrids ca. 10.00.000x mehr Performance verbrät als ein eventuell vorhandener Unterschied zwischen FOR- und WHILE-Schleife kannst Du dich getrost auf andere Sachen konzentrieren.
Z.B. das allseits beliebte: "Trenne Funktion und Darstellung". Verwende also kein Stringgrid, um 100-Tausende von Daten im Speicher zu halten. Da wird sowieso niemals jemand durchscrollen. Verwende ein Grid nur zur Darstellung eines Ausschnittes deiner Tabelle, so wie z.B. das TDBGrid, das einen kleinen Ausschnitt aus einer beliebig großen Datenmenge (TDataset) zeigt. |
Re: FOR oder WIHLE was ist schneller (Stringgrid befüllen)
@alzaimar: ja das ist bereits schon so, alle daten die ich brache sind in records gespeichert, im stringgrid werden sie nur aufbereitet angezeigt!
|
Re: FOR oder WIHLE was ist schneller (Stringgrid befüllen)
Das liegt ja nur an der Anzeige. Die ist grottenlahm. Mache das mal so :
Sg.hide; Füllen Sg.show; |
Re: FOR oder WIHLE was ist schneller (Stringgrid befüllen)
Zeig mal ein wenig Code. Wie gesagt, ich vermute, Du hast einfach zu viele Records. Hier wäre der Einsatz eines TDatasets und TDBGrid wohl angebracht. Alternativ könntest Du eine TListView im OwnerData-Modus laufen oder nimmst gleich ein TVirtualTreeView, das dafür besonders geeignet ist.
|
Re: FOR oder WIHLE was ist schneller (Stringgrid befüllen)
Also das ganze ist ein Tool für meinen Arbeitgeber zur Planung von Schichtplänen, leider ist die Sache schon soweit fotgeschritten das es jetzt nicht so einfach ist hier ein paar Codefetzen hinzuwerfen
Also das Stringgrid ist so aufgebaut Kostenstelle Arbeitsplatzgruppe Name Personnummer Schicht 1.1 2.1 3.1 4.1 .....das ganze für 4 Wcohen im Testmodus sind 45 Mitarbeiter eingepflegt der Record dafür sieht so aus
Delphi-Quellcode:
dann get es weiter mit einen "Übersteuern" Record
type
TData = record Name : String[20]; Vorname : String[15]; Personalnummer : String[15]; Kostenstelle : String[15]; Arbeitsplatzgruppe : String[16]; Ersthelfer : Boolean; Vorarbeiter : Boolean; Leiharbeiter : Boolean; Username : String[20]; Telefonnummer : String[20]; Meister : Boolean; Schicht : String[60]; StartSchicht : String[2]; Start_Date : String[20]; ErlaubteKST : String[255]; EinsatzMoeglichkeit : String[255]; end; wird benötigt um Änderungen im Schitplan anzuzeigen und nicht die eigentlichen Schicht abändern zu müssen so das der einzelne Mitarbeiter immer im gleichen Rhythmus bleibt
Delphi-Quellcode:
type
TChangeData = record SchichtTyp : String[5]; Datum : TDateTime; Personalnummer : String[15]; Kostenstelle : String[15]; Arbeitsplatzgruppe : String[15]; Wochenweise : Boolean; end; type TUebersteuern = record Daten : Array [1..100000] of TChangeData; Count :integer; end; die function um die schichten zu berechnen sieht so aus
Delphi-Quellcode:
function GetSchicht(Mitarbeiter:TData;KW:Integer;Year:Integer;Datum:TDateTime;Weekly:Boolean):String;
var SchichtSystem :String; EinzelSchicht :String; EinzelSchichtTag :String; i,x :integer; // savepos :integer; SchichtList :TStringList; ErrechnetesDatum :TDateTime; EndDatum :TDateTime; Tagessumme :Integer; y :Integer; //5tagesansicht übersteuert in wochenansicht q :Integer; SaveDate :Tdatetime; SaveSchicht :String; tagecounter :Integer; begin if mitarbeiter.Schicht='' then exit; SchichtList:= TStringList.Create; //+++++++Schichtsystem des Mitarbeiters suchen++++++++++ for i:=1 to Settings.SchichtenCount do begin if Mitarbeiter.Schicht=settings.Schichten[i].Name then begin SchichtSystem:=settings.Schichten[i].Reihenfolge; break; end; end; //+++++++Schichtsystem auseinander flücken for i:=1 to Length(SchichtSystem) do begin if SchichtSystem[i]<>';' then begin EinzelSchicht:=EinzelSchicht+SchichtSystem[i]; end else begin SchichtList.Add(EinzelSchicht); //main_window.ListBox1.Items.Add(EinzelSchicht) ; EinzelSchicht:=''; end; end; //Anfangschichtsystem finden mit x vergleichen gegen hinterlegten string x:=StrtoInt(Mitarbeiter.StartSchicht)-1; //################################## Ansicht Tageweise/Wochenweise ################################# //################################## Ansicht Tageweise/Wochenweise ################################# //Tage pro schicht ermitteln und ab startdatum rechnen Tagessumme:=0; ErrechnetesDatum:=0; if Weekly=true then Datum:=StartOfAWeek(Year, KW, 1); //noch end datum eintragen errechtet aus der kw while ErrechnetesDatum <= Datum do begin EinzelSchichtTag:=SchichtList.Strings[x]; EinzelSchichtTag:=StringReplace(EinzelSchichtTag,'N','', [rfReplaceAll]); EinzelSchichtTag:=StringReplace(EinzelSchichtTag,'S','', [rfReplaceAll]); EinzelSchichtTag:=StringReplace(EinzelSchichtTag,'F','', [rfReplaceAll]); EinzelSchichtTag:=StringReplace(EinzelSchichtTag,'W','', [rfReplaceAll]); Tagessumme:=Tagessumme+StrToInt(EinzelSchichtTag); ErrechnetesDatum:=StrToDate(Mitarbeiter.Start_Date)+Tagessumme; if pos('F',SchichtList.Strings[x])>0 then result:='F';//'Frühschicht'; if pos('S',SchichtList.Strings[x])>0 then result:='S';//'Spätschicht'; if pos('N',SchichtList.Strings[x])>0 then result:='N';//'Nachtschicht'; if pos('W',SchichtList.Strings[x])>0 then result:='.';//'Wochenende'; inc(x); if x> SchichtList.Count-1 then x:=0; end; //++++++++++++++++++++++++++++Wochenende setzten++++++++++++++++++++++++++++++ if Weekly=false then if DayOfTheWeek(Datum)>5 then result:='.'; ///// //++++++++++++++++++++++++++++Wochenende setzten++++++++++++++++++++++++++++++ //##############################Übersteuern Start################################# //################################################################################ for y:=1 to Uebersteuern.Count do begin if Uebersteuern.Daten[y].Personalnummer=Mitarbeiter.Personalnummer then begin if Uebersteuern.Daten[y].Wochenweise=true then begin if weekly=true then //ansicht in KW begin if (Uebersteuern.Daten[y].Datum=StartOfAWeek(Year, KW, 1)) then result:=Uebersteuern.Daten[y].SchichtTyp; end else begin //ansicht Tageweise buchung alle 5 arbeitstage! if (Uebersteuern.Daten[y].Datum<=Datum) and (Uebersteuern.Daten[y].Datum+4>=Datum) then result:=Uebersteuern.Daten[y].SchichtTyp; end; end else begin //tagesansicht if weekly=false then begin if Uebersteuern.Daten[y].Datum=Datum then result:=Uebersteuern.Daten[y].SchichtTyp; end else begin //wochenasicht gucken ob 5 gleiche einträge vorhanden sind if Uebersteuern.Daten[y].Datum=Datum then begin SaveDate:=StartOfTheWeek(Uebersteuern.Daten[y].Datum); SaveSchicht:=Uebersteuern.Daten[y].SchichtTyp; tagecounter:=0; q:=1; //nochmal die daten durchsuchen für einträge in gleicher woche mit gleicher schicht while q<=Uebersteuern.Count do begin if (Uebersteuern.Daten[q].Personalnummer=Mitarbeiter.Personalnummer) then begin if (Uebersteuern.Daten[q].Datum=SaveDate+tagecounter) and (Uebersteuern.Daten[q].SchichtTyp=SaveSchicht) then begin inc(tagecounter); q:=0; if tagecounter>4 then break; end end; inc(q) end; if tagecounter>4 then result:=SaveSchicht; end; end; end; end; end; //##############################Übersteuern Ende################################## //sollte der Starttermin vor dem aktuellen datum liegen in der vergangenheit if weekly=true then if StartOfAWeek(Year, KW, 1) <StrToDate(Mitarbeiter.Start_Date) then result:='xxx'; if weekly=false then if Datum <StrToDate(Mitarbeiter.Start_Date) then result:='xxx'; SchichtList.Free; end; |
Alle Zeitangaben in WEZ +1. Es ist jetzt 07:43 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