Geschwindigkeit Schleifen

Für Fragen von Einsteigern und Programmieranfängern...
Anfänger33
Beiträge: 25
Registriert: Sa 15. Feb 2025, 13:33

Geschwindigkeit Schleifen

Beitrag von Anfänger33 »

Anfängerfrage:
Welche Schleife wird am schnellsten abgearbeitet (FOR-,WHILE- oder Repeat-Schleife)?
Welche Schleife sollte man am besten nehmen?

Benutzeravatar
m.fuchs
Lazarusforum e. V.
Beiträge: 2826
Registriert: Fr 22. Sep 2006, 19:32
OS, Lazarus, FPC: Winux (Lazarus 2.0.10, FPC 3.2.0)
CPU-Target: x86, x64, arm
Wohnort: Berlin
Kontaktdaten:

Re: Geschwindigkeit Schleifen

Beitrag von m.fuchs »

Du nimmst am besten die, welche zu deinem Anwendungsfall passt.

Anfängerfaustformel: Wenn du weißt wieviele Durchgänge es geben wird -> For-To-Do.
Soll etwas geschehen solange ein bestimmter Zustand vorliegt -> While-Do.
Soll etwas geschehen bis ein bestimmter Zustand vorliegt -> Repeat-Until.
Das ist jetzt natürlich etwas vereinfacht, aber auf alle Fälle kommt es auf deinen Anwendungsfall an.

Wenn du an den Punkt angekommen bist wo die Ausführungsgeschwindigkeit der Steuerung der Schleife (also nicht das was innerhalb der Schleife passiert) relevant ist, dann bist du sowieso schon bei Assembler o.Ä. angekommen.

Ignoriere also den Faktor Geschwindigkeit bitte konplett bei der Auswahl des Schleifentyps.

Gibt es ein konkretes Problem zu deiner Frage oder ist sie eher allgemein?
Software, Bibliotheken, Vorträge und mehr: https://www.ypa-software.de

Anfänger33
Beiträge: 25
Registriert: Sa 15. Feb 2025, 13:33

Re: Geschwindigkeit Schleifen

Beitrag von Anfänger33 »

Vielen Dank für die ausführlichen Erläuterungen und die Hinweise zum Einsatzzweck (Faustformel).
Damit kann ich was anfangen.

Die Frage ging mehr in Richtung allgemeines Verständnis. In vielen Toutorials werden die Schleifentypen erläutert, aber wann man welche Typ einsetzt bleibt dem User (=Anfänger) überlassen. Sonst würde man ja nicht ein Anfängertoutorial durcharbeiten.

Habe mal mit C, C++ und Qt angefangen. Da ist die Lernkurve extrem steil.
Zur Zeit arbeite ich einige Toutorials auf Youtube durch. Mit Lazarus konne ich im großen und ganzen relativ gut zurecht.

Benutzeravatar
Zvoni
Beiträge: 414
Registriert: Fr 5. Jul 2024, 08:26
OS, Lazarus, FPC: Windoof 10 Pro (Laz 2.2.2 FPC 3.2.2)
CPU-Target: 32Bit
Wohnort: BW

Re: Geschwindigkeit Schleifen

Beitrag von Zvoni »

Nachtrag zu "While" bzw. "Repeat"
"Repeat/Until" wird mindestens einmal ausgeführt, während "While" (bzw. auch For-Loop) auch keinmal ausgeführt werden kann.

Beim For-Loop werden die Grenzen EINMAL ermittelt und dann durchgezogen.
Eine Änderung der Grenze innerhalb des For-Loops hat keine Auswirkung (Was man eh nicht machen sollte).
Desweiteren sollte man bei einem For-Loop auch die Finger von der Iterator-Variablen lassen (gabs erst vor kurzem ne Diskussion im englischen Forum)

Bei Repeat bzw. While wird die Ausstiegsbedingung jedesmal neu ermittelt. Hier ist nicht mal eine Iterator-Variable notwendig
Denkt mal an Recordsets einer DB-Abfrage

Code: Alles auswählen

Repeat
  DoSomething;
  RS.Next;
Until RS.EOF;
Generell zu Schleifen und Speed:
Wenn du der Meinung bist, dass deine Schleife zu lang braucht, dann ist es erfahrungsgemäss in 99% der Fälle das, was innerhalb der Schleife passiert, was dich bremst, und nicht die Art, WELCHE Schleife du verwendest (Obwohl es auch da Optimierungs-Ansätze gibt)
Ein System sie alle zu knechten, ein Code sie alle zu finden,
Eine IDE sie ins Dunkel zu treiben, und an das Framework ewig zu binden,
Im Lande Redmond, wo die Windows drohn.

alfware17
Beiträge: 218
Registriert: Di 14. Dez 2010, 23:27

Re: Geschwindigkeit Schleifen

Beitrag von alfware17 »

Über die "Geschwindigkeit" habe ich mir bisher auch selten Gedanken gemacht, da hier vieles der Compiler optimieren könnte.
Eher sind schon die bereits genannten praktischen Probleme relevant:
- reicht eine feste Anzahl zum Beispiel zum Durchlaufen von Feldern
- macht es einen Unterschied bei repeat/while weil man zB manche Lauf-/Abbruchbedingen noch nicht weiß und/oder lieber positiv als negativ ausdrücken will
- und ja, ist es notwendig auf die iterierten Objekte zuzugreifen (verändern sollte man lassen wenn man kein Experte ist)

Ich kenne aus den genannten C-Sprachen und zB in Java oder Python die ziemlich elegante for-each Schleife, wo man Indexe einsparen und auch noch sicher bei den Typen sein kann. Gibt es etwas ähnliches auch in Free Pascal?

Benutzeravatar
m.fuchs
Lazarusforum e. V.
Beiträge: 2826
Registriert: Fr 22. Sep 2006, 19:32
OS, Lazarus, FPC: Winux (Lazarus 2.0.10, FPC 3.2.0)
CPU-Target: x86, x64, arm
Wohnort: Berlin
Kontaktdaten:

Re: Geschwindigkeit Schleifen

Beitrag von m.fuchs »

alfware17 hat geschrieben: Di 18. Feb 2025, 09:18 Ich kenne aus den genannten C-Sprachen und zB in Java oder Python die ziemlich elegante for-each Schleife, wo man Indexe einsparen und auch noch sicher bei den Typen sein kann. Gibt es etwas ähnliches auch in Free Pascal?
Aber ja:

Code: Alles auswählen

program ForInTest;
{$MODE ObjFPC}{$H+}

uses
  Classes;

var
  s: String = 'Dies ist ein Test.';
  c: Char;

begin
  for c in s do
    WriteLn(c);
end.
https://wiki.freepascal.org/for-in_loop
Software, Bibliotheken, Vorträge und mehr: https://www.ypa-software.de

Benutzeravatar
Zvoni
Beiträge: 414
Registriert: Fr 5. Jul 2024, 08:26
OS, Lazarus, FPC: Windoof 10 Pro (Laz 2.2.2 FPC 3.2.2)
CPU-Target: 32Bit
Wohnort: BW

Re: Geschwindigkeit Schleifen

Beitrag von Zvoni »

m.fuchs hat geschrieben: Di 18. Feb 2025, 09:33
alfware17 hat geschrieben: Di 18. Feb 2025, 09:18 Ich kenne aus den genannten C-Sprachen und zB in Java oder Python die ziemlich elegante for-each Schleife, wo man Indexe einsparen und auch noch sicher bei den Typen sein kann. Gibt es etwas ähnliches auch in Free Pascal?
Aber ja:

Code: Alles auswählen

program ForInTest;
{$MODE ObjFPC}{$H+}

uses
  Classes;

var
  s: String = 'Dies ist ein Test.';
  c: Char;

begin
  for c in s do
    WriteLn(c);
end.
https://wiki.freepascal.org/for-in_loop
Funzt auch mit Sets/Enums

Code: Alles auswählen

program Project1;
Type
  TTest = (ftEins, ftZwei, ftDrei, ftVier);
Var
  T:set of TTest;
  X:TTest;
begin
  T:=[ftEins, ftVier];
  For X In T Do Writeln(X);
end.
Ein System sie alle zu knechten, ein Code sie alle zu finden,
Eine IDE sie ins Dunkel zu treiben, und an das Framework ewig zu binden,
Im Lande Redmond, wo die Windows drohn.

Warf
Beiträge: 2158
Registriert: Di 23. Sep 2014, 17:46
OS, Lazarus, FPC: Win10 | Linux
CPU-Target: x86_64

Re: Geschwindigkeit Schleifen

Beitrag von Warf »

For schleifen machen deutlich mehr als While oder Repeat schleifen, daher sind die natürlich offensichtlich langsamer. Aber wenn du eine While oder Repeat schleife baust die das selbe macht wie eine For schleife bist du auch nicht schneller.
Wenn du eine For schleife brauchst, brauchst du eine For schleife, simple as that.

Genauso der unterschied zwischen while und repeat, das eine macht den Vergleich oben das andere Unten, das hat natürlich auswirkungen auf die Performance, aber wenn du einen Kopfbasierten vergleich brauchst kannst du kein Repeat nehmen und wenn du einen Fußbasierten vergleich brauchst kein While.
Jedweder geschwindigkeitsunterschied ergibt sich daraus das die schleifen andere Sachen machen, du nutzt die Schleife die du brauchst, und dann musst du mit den Konsequenzen leben.

Das gesagt, es gibt eine Optimierung die oftmals gemacht wird. Wenn du eine sehr spezielle Exit condition hast die sich aus deinem Flow ergibt, dann ist das folgende:

Code: Alles auswählen

repeat
  // Mach was
  if ExitCondition then Break;
until False;
Effizienter als die alternativen.

Benutzeravatar
fliegermichl
Lazarusforum e. V.
Beiträge: 1663
Registriert: Do 9. Jun 2011, 09:42
OS, Lazarus, FPC: Lazarus Fixes FPC Stable
CPU-Target: 32/64Bit
Wohnort: Echzell

Re: Geschwindigkeit Schleifen

Beitrag von fliegermichl »

Warf hat geschrieben: Di 18. Feb 2025, 11:29 [...]

Das gesagt, es gibt eine Optimierung die oftmals gemacht wird. Wenn du eine sehr spezielle Exit condition hast die sich aus deinem Flow ergibt, dann ist das folgende:

Code: Alles auswählen

repeat
  // Mach was
  if ExitCondition then Break;
until False;
Effizienter als die alternativen.
Das hat bei mir irgendwie "Geschmäckle". Hin und wieder mache ich sowas auch. Macht den Code, gerade wenn er umfangreich ist, aber auch schwerer lesbar.

Benutzeravatar
Zvoni
Beiträge: 414
Registriert: Fr 5. Jul 2024, 08:26
OS, Lazarus, FPC: Windoof 10 Pro (Laz 2.2.2 FPC 3.2.2)
CPU-Target: 32Bit
Wohnort: BW

Re: Geschwindigkeit Schleifen

Beitrag von Zvoni »

Warf hat geschrieben: Di 18. Feb 2025, 11:29 Das gesagt, es gibt eine Optimierung die oftmals gemacht wird. Wenn du eine sehr spezielle Exit condition hast die sich aus deinem Flow ergibt, dann ist das folgende:

Code: Alles auswählen

repeat
  // Mach was
  if ExitCondition then Break;
until False;
Effizienter als die alternativen.
Ich mache sowas nur, wenn ich vor dem Ende einer Schleife rausspringen muss.
Also eher in der Art

Code: Alles auswählen

repeat
  // Mach was, dass Auswirkung auf ExitCondition hat
  if ExitCondition then Break;
  // Mache weiter, dass Auswirkung auf ExitCondition hat
until ExitCondition;
Ein System sie alle zu knechten, ein Code sie alle zu finden,
Eine IDE sie ins Dunkel zu treiben, und an das Framework ewig zu binden,
Im Lande Redmond, wo die Windows drohn.

Mathias
Beiträge: 6973
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: Geschwindigkeit Schleifen

Beitrag von Mathias »

Was ich in der for Schleife von Pascal vermisse, das der Step entweder +1 oder -1 sein muss. Bei C oder gar beim alten GW-BASIC sind float in der Schleife gestattet.
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Benutzeravatar
Zvoni
Beiträge: 414
Registriert: Fr 5. Jul 2024, 08:26
OS, Lazarus, FPC: Windoof 10 Pro (Laz 2.2.2 FPC 3.2.2)
CPU-Target: 32Bit
Wohnort: BW

Re: Geschwindigkeit Schleifen

Beitrag von Zvoni »

Mathias hat geschrieben: Di 18. Feb 2025, 13:13 Was ich in der for Schleife von Pascal vermisse, das der Step entweder +1 oder -1 sein muss. Bei C oder gar beim alten GW-BASIC sind float in der Schleife gestattet.
VBA/VB6

Code: Alles auswählen

Dim i As Long
For i=0 To 99 Step 2
//DoSomething
Next
Fragen?
Und ja, vermisse ich auch.....
Ein System sie alle zu knechten, ein Code sie alle zu finden,
Eine IDE sie ins Dunkel zu treiben, und an das Framework ewig zu binden,
Im Lande Redmond, wo die Windows drohn.

Mathias
Beiträge: 6973
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: Geschwindigkeit Schleifen

Beitrag von Mathias »

Sowas habe ich auch schon vermisst, so musst man sich mit einer while-Schleife behelfen.

Code: Alles auswählen

var
  i: Single
begin
  for i := 0.5 to 3.5 step 0.5 do begin
    foo;
  end; 
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Warf
Beiträge: 2158
Registriert: Di 23. Sep 2014, 17:46
OS, Lazarus, FPC: Win10 | Linux
CPU-Target: x86_64

Re: Geschwindigkeit Schleifen

Beitrag von Warf »

Mathias hat geschrieben: Di 18. Feb 2025, 13:13 Was ich in der for Schleife von Pascal vermisse, das der Step entweder +1 oder -1 sein muss. Bei C oder gar beim alten GW-BASIC sind float in der Schleife gestattet.
Naja in C ist der for loop nur ein glorifizierter While loop, in Pascal ist for tatsächlich semantisch deutlich stärker, so geht z.B. das

Code: Alles auswählen

for i:=Integer.MaxValue-3 to Integer.MaxValue do
Was in C nicht so einfach geht wegen überlauf.

Bezüglich floats, hab ich mal das hier gebastelt: https://gitlab.com/freepascal.org/fpc/s ... quests/856
Erlaubt for loops über alle typen die + mit Integers überladen haben, auch selbst definierte Record typen :)

Stevie
Beiträge: 175
Registriert: Di 27. Feb 2024, 22:40

Re: Geschwindigkeit Schleifen

Beitrag von Stevie »

... an diesen Stellen zeigt Pascal eben seinen Ursprung als Lehr-Sprache. Das 'FOR' sollte eine vorgegebene Anzahl an Iterationen über eine Folge von Anweisungen ermöglichen. Und im Sinne dieser Definition gibt es keine Schrittweite. Hierfür sieht die Sprache das 'WHILE' vor, das keine vorab definierte Anzahl an Durchläufen erzwingt und somit auch eine freie Wahl der Schrittweite ermöglicht. Das ist einfach zu erklären und dem Einsteiger in der Lehre gut zu vermitteln.

Das unterscheidet Pascal aber eben von 'C', in dessen Sprachentwurf die oberste Maximen die Nützlichkeit und die Effizienz eines jeden Sprachmerkmals waren. Weil eine andere Schrittweite oder gar eine Veränderung der Schleifenlänge zur Laufzeit irgendwie hilfreich waren, hatten sie sich damit für 'C' schon ausreichend gerechtfertigt.

Antworten