Zeilenweise Ausgabe optimieren...

Für Fragen von Einsteigern und Programmieranfängern...
Antworten
alfware17
Beiträge: 224
Registriert: Di 14. Dez 2010, 23:27

Zeilenweise Ausgabe optimieren...

Beitrag von alfware17 »

Also das Thema ist bei mir dauernd interessant u.a in einem größeren Sortierfall, wenn Zwischendateien gebildet, sortiert und wieder eingemischt werden müssen und dann tatsächlich das Mischen/Kopieren der Flaschenhals ist und 2/3 der Zeit benötigt. An einer Beschleunigung der einfachen Readln/Writeln war ich schon zig Jahre interessiert und habe scheinbar nie etwas gefunden. Nun schon (siehe meine Anlage).
Was mir (negativ) auffiel, das Stringlist.LoadFromFile ist sehr fix, das StringlistSaveToFile dagegen eine mehr als lahme Ente. So lahm, daß ich beim Sortieren von der Stringlist Abstand genommen und eine eigene Liste implementiert hatte. Die Sortieralgorithmen halten sich wohl die Waage, nur daß die Stringliste bei Millionen Zeilen abkackt und meins nicht, egal Zwischendateien brauchte ich trotzdem.
Nun habe ich mit dem SaveLineBuffered (Unit OptIO) anscheinend etwas Brauchbares gefunden, was das einfache Writeln doch topt bzw ja dropt und das ReadLineBuffered nach längeren Irren und Wirren auch. Habe bei meinen Zieldatenstrukturen (Array fest bzw dynamisch, einfach bzw doppelt verkettete Listen, Stacks usw) keine Fehler mehr gefunden.
Dann wollte ich mich wagen an das StringList.SaveToFileFast und es scheint mir auch gelungen. Jedenfalls finde ich in den Ausgaben keine offensichtlichen Fehler mehr und die Laufzeit ist akzeptabel (mehr als 10x schneller als SaveToFile und auch noch bedeutend schneller als das einfache Writeln). Könnte da bitte mal jemand drüberschauen? Habe ich etwas übersehen oder gibt es noch schnellere Kandidaten? Den Stringbuilder hatte ich auch am Wickel aber ich fand das Blockwrite für mich logischer.
Dateianhänge
saveopt.zip
(289.57 KiB) 109-mal heruntergeladen

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

Re: Zeilenweise Ausgabe optimieren...

Beitrag von Mathias »

An einer Beschleunigung der einfachen Readln/Writeln war ich schon zig Jahre interessiert und habe scheinbar nie etwas gefunden.
Evtl ist FileStream oder MemoryStream eine Alternative. Read und Write sind nicht unbedingt Raketen, vor allem wen man Byteweise einliest.
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

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

Re: Zeilenweise Ausgabe optimieren...

Beitrag von alfware17 »

Ich möchte eigentlich schon zeilenweise nicht byteweise lesen.
Was machen die beiden von dir genannten Klassen(?) anders als das Blockwrite oder Stringbuilder?

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

Re: Zeilenweise Ausgabe optimieren...

Beitrag von alfware17 »

Ich habe mich nun für TStringArray und entweder
- eine Kombination aus normalen Readln und gepufferten Blockwrite entschieden
- eventuell auch ein neues, auf TStream basierendes ReadAllLines und WriteAllLines, welches noch ca 10% schneller wäre, aber bei 32bit zu früh an Speichergrenzen gerät (vielleicht kombiniere ich das auch).
Den notwendigen Array Sort habe ich gefunden, er ist sogar schneller als mein bisheriger Listen/Pointer-basierter.

Aber beim Testen ist mir nun eine Sache aufgefallen, die mir bisher nicht so bewußt war: Der Standard SL.Sort ist sooooo langsam? Bis zu 10x langsamer?
25s bei 2 Mio Zeilen zufälligen Inhaltes gegenüber max 2s beim Array-Sort. Mein altes Projekt ist da bei 4s allerdings schon mit Teilen und Merge (standardmäßig bei 1 Mio).

Ich kann das bei einer Standard-Methode einfach nicht glauben, was mache ich falsch. Ich dachte bisher immer es liegt am SL.SaveToFile (und habe den optimiert). Aber der Sort selber als Bremse?

Code: Alles auswählen

PROGRAM XCopy7; (* StringList(SL), SL.LoadFromFile, SL.SaveToFileFast SL.Sort *)

{$mode objfpc}

USES
  Stdio, Zeit, WaitKey, Classes, SLOpt;

VAR
  EinName, AusName: STRING;
  EinZahl, AusZahl: CARD;
  Sortieren : BOOLEAN;
  SL: TStringList;

BEGIN
  Intervall_Start(10);
  Sortieren := FALSE;
  IF PARAMSTR(1) <> '' THEN EinName := PARAMSTR(1)
                       ELSE EinName := 'input' + {$IFNDEF DOS} '12' {$ELSE} '03' {$ENDIF} + '.txt';
  IF PARAMSTR(2) <> '' THEN AusName := PARAMSTR(2)
                       ELSE AusName := 'output' + {$IFNDEF DOS} '12' {$ELSE} '03' {$ENDIF} + '.txt';
  IF (PARAMSTR(3) <> '') OR ((PARAMSTR(1) = '') AND (PARAMSTR(2) = '')) THEN Sortieren := TRUE;
  Writeln('Kopiere ('+_ue+'ber SL) ', EinName, ' nach ', AusName);

  Writeln('SL LoadFromFile ', Intervall_Start(1));
  SL := TSTringList.Create;
  SL.LoadFromFile(EinName);
  EinZahl := SL.Count;
  Writeln(Intervall_Stop(1) + ' ' + Intervall_Dauer(1));
  Writeln('Anzahl Eingabe: ', StrCard(EinZahl));

  IF Sortieren THEN BEGIN
    Writeln('Sortieren SL ', Intervall_Start(2));
    SL.Sort;
    Writeln(Intervall_Stop(2) + ' ' + Intervall_Dauer(2));
    Writeln('Zeilen SL/Sortiert: ', StrCard(SL.Count));
  END;

  Writeln('SL SaveToFileFast ', Intervall_Start(3));
  //SL.SaveToFile(AusName);
  SL.SaveToFileFast(AusName);
  AusZahl := SL.Count;
  Writeln(Intervall_Stop(3) + ' ' + Intervall_Dauer(3));
  Writeln('Anzahl Ausgabe: ', StrCard(AusZahl));

  Intervall_Stop(10);
  Writeln('Gesamt: ', Intervall_Dauer(10));
  Wait;
END.

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

Re: Zeilenweise Ausgabe optimieren...

Beitrag von Mathias »

Aber beim Testen ist mir nun eine Sache aufgefallen, die mir bisher nicht so bewußt war: Der Standard SL.Sort ist sooooo langsam? Bis zu 10x langsamer?
Da wäre recht spannend, was die STringList für eine Sortierroutine verwendet. Ob da was anderes als QSort verwendet wird ?
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Benutzeravatar
theo
Beiträge: 10976
Registriert: Mo 11. Sep 2006, 19:01

Re: Zeilenweise Ausgabe optimieren...

Beitrag von theo »

Mathias hat geschrieben: Do 7. Aug 2025, 14:14 Da wäre recht spannend, was die STringList für eine Sortierroutine verwendet. Ob da was anderes als QSort verwendet wird ?
Zu dumm, dass wir keinen Quelltext haben... :mrgreen:
procedure TStringList.QuickSort(L, R: Integer; CompareFn: TStringListSortCompare );

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

Re: Zeilenweise Ausgabe optimieren...

Beitrag von alfware17 »

Mathias hat geschrieben: Do 7. Aug 2025, 14:14
Aber beim Testen ist mir nun eine Sache aufgefallen, die mir bisher nicht so bewußt war: Der Standard SL.Sort ist sooooo langsam? Bis zu 10x langsamer?
Da wäre recht spannend, was die STringList für eine Sortierroutine verwendet. Ob da was anderes als QSort verwendet wird ?
ich habe mittlerweile mit ChatGPT herausgefunden, daß da wohl eine alte Delphi-Routine sortiert, die nie rausgenommen wurde, weil anscheinend kein Bedarf an Sortieren bei so großen Stringlists und weil wohl Rücksicht auf andere Methoden genommen wird, die TStringList hat (sorry falls ich das falsch wiedergebe).

Aber!! Und dann kam die große Entdeckung des Tages für mich - und wieder sorry falls Euch allen das so klar ist, ich bin in Bezug auf die Lazarus-Objekte noch immer Anfänger und ich war erstaunt und leicht euphorisiert, als ich las, die einzelnen Strings der TStringList lassen sich über einen Index ansprechen. Also A[0] bis A[len-1],
Darauf hin habe ich glatt meinen TStringArray Quicksort 1:1 darauf angesetzt und voíla nur 5-10% langsamer als beim TStringArray. Aber schon mal nicht mehr 10 MAL langsamer.
Dann habe ich noch die Compare-Funktion entschlackt und nun sind die beiden Quicksorts vergleichbar. Rätsel gelöst und ich stehe vor der Qual der Wahl, welches ich in meinem Anwendungsprogramm nehmen soll. TStringList lädt und sichert doch noch einen Tick schneller, dafür ist bei TStringArray der Sort etwas fixer. Mal sehen. Meinen aktualisierten Benchmark werde ich noch nachreichen, dazu fehlt mir aber noch ein Puzzleteil und das ist in den Tiefen meines Stacks äh Kellers gut versteckt.

Code: Alles auswählen

UNIT SLOpt;

{$mode objfpc}{$H+}

INTERFACE

USES
  Classes, SysUtils;

TYPE
  TStringCompareFunc = FUNCTION(CONST A, B: STRING): INTEGER;

  TStringListHelper = CLASS HELPER FOR TStringList
    PROCEDURE SaveToFileFast(CONST FileName: STRING);
    PROCEDURE QuickSortFast;
  END;

IMPLEMENTATION

FUNCTION CompareStringsFast(CONST TextA, TextB: STRING): INTEGER;
BEGIN
  // Schneller, bin_aerer Vergleich (ohne Gro_sz-/Kleinschreibung zu ignorieren)
  CompareStringsFast := CompareStr(TextA, TextB);
END;

PROCEDURE QuickSortSL(Strings: TStringList; LeftIndex, RightIndex: INTEGER; CompareFunc: TStringCompareFunc);
VAR
  IndexLeft, IndexRight: INTEGER;
  Pivot, Temp: STRING;
BEGIN
  IndexLeft := LeftIndex;
  IndexRight := RightIndex;
  Pivot := Strings[(LeftIndex + RightIndex) DIV 2];
  REPEAT
    WHILE CompareFunc(Strings[IndexLeft], Pivot) < 0 DO INC(IndexLeft);
    WHILE CompareFunc(Strings[IndexRight], Pivot) > 0 DO DEC(IndexRight);
    IF IndexLeft <= IndexRight THEN BEGIN
      Temp := Strings[IndexLeft];
      Strings[IndexLeft] := Strings[IndexRight];
      Strings[IndexRight] := Temp;
      INC(IndexLeft);
      DEC(IndexRight);
    END;
  UNTIL IndexLeft > IndexRight;
  IF LeftIndex < IndexRight
    THEN QuickSortSL(Strings, LeftIndex, IndexRight, CompareFunc);
  IF IndexLeft < RightIndex
    THEN QuickSortSL(Strings, IndexLeft, RightIndex, CompareFunc);
END;

PROCEDURE TStringListHelper.QuickSortFast;
BEGIN
  IF Self.Count > 1
    THEN QuickSortSL(Self, 0, Self.Count - 1, @CompareStringsFast);
END;

PROCEDURE TStringListHelper.SaveToFileFast(CONST FileName: STRING);
CONST
  BufferSize = 65536;
VAR
  OutputFile: FILE;
  OutputBuffer: ARRAY[0..BufferSize - 1] OF BYTE;
  BufferPtr: PByte;
  BufferFill, LineLength, LineIndex: INTEGER;
  LineData: STRING;
BEGIN
  AssignFile(OutputFile, FileName);
  System.Rewrite(OutputFile, 1);
  BufferPtr := @OutputBuffer[0];
  BufferFill := 0;
  FOR LineIndex := 0 TO Self.Count - 1 DO BEGIN
    LineData := Self[LineIndex] + LineEnding;
    LineLength := Length(LineData);
    IF BufferFill + LineLength > BufferSize THEN BEGIN
      BlockWrite(OutputFile, OutputBuffer, BufferFill);
      BufferFill := 0;
      BufferPtr := @OutputBuffer[0];
    END;
    System.Move(LineData[1], BufferPtr^, LineLength);
    INC(BufferPtr, LineLength);
    INC(BufferFill, LineLength);
  END;
  IF BufferFill > 0
    THEN BlockWrite(OutputFile, OutputBuffer, BufferFill);
  CloseFile(OutputFile);
END;

BEGIN
END.


wp_xyz
Beiträge: 5245
Registriert: Fr 8. Apr 2011, 09:01

Re: Zeilenweise Ausgabe optimieren...

Beitrag von wp_xyz »

alfware17 hat geschrieben: Do 7. Aug 2025, 15:02 ich habe mittlerweile mit ChatGPT herausgefunden, daß da wohl eine alte Delphi-Routine sortiert, die nie rausgenommen wurde, weil anscheinend kein Bedarf an Sortieren bei so großen Stringlists und weil wohl Rücksicht auf andere Methoden genommen wird, die TStringList hat (sorry falls ich das falsch wiedergebe).
Leider weiß man bei KI nie, ob eine Aussage die Wahrheit oder Einbildung ist...

Den Quicksort musst du in TStringList nicht selbst implementieren, der ist (als private Methode "QuickSort") schon eingebaut, wird aber nur aktiviert, wenn die Eigenschaft Sorted=true ist (und damit wird auch gleich sortiert).

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

Re: Zeilenweise Ausgabe optimieren...

Beitrag von alfware17 »

wp_xyz hat geschrieben: Do 7. Aug 2025, 15:13
alfware17 hat geschrieben: Do 7. Aug 2025, 15:02 ich habe mittlerweile mit ChatGPT herausgefunden, daß da wohl eine alte Delphi-Routine sortiert, die nie rausgenommen wurde, weil anscheinend kein Bedarf an Sortieren bei so großen Stringlists und weil wohl Rücksicht auf andere Methoden genommen wird, die TStringList hat (sorry falls ich das falsch wiedergebe).
Leider weiß man bei KI nie, ob eine Aussage die Wahrheit oder Einbildung ist...

Den Quicksort musst du in TStringList nicht selbst implementieren, der ist (als private Methode "QuickSort") schon eingebaut, wird aber nur aktiviert, wenn die Eigenschaft Sorted=true ist (und damit wird auch gleich sortiert).
Wird dann beim Load gleich sortiert? Oder erst wenn ich das Sorted (mit meine.Sorted:=true nehme ich an?) setze. Sag jetzt nicht, ich kann es doch ausprobieren...
Mache ich sowieso, aber erstmal war ich so stolz daß ich das mit dem Zugriff über die Indexe herausgefunden habe.
Ich nahm an der private Quicksort sieht dann genau so aus, wie der den ich in den Helper gebaut habe, aber das was ich im Github sah, sieht irgendwie ähnlich aber doch anders aus. Und meine Frage bleibt, warum ist der 10x langsamer?

Die Quicksort Routine im Github löst den zweiten rekursiven Aufruf irgendwie in einem Repeat drum herum auf. Und es wird AnsiCompare benutzt. Aber ob das so ein Zehnfaches ausmacht? Ich habe schon gesucht, ob ich das falsch aufrufe, aber anscheinend ist der Unterschied in der Performance da

Code: Alles auswählen

procedure TStringList.QuickSort(L, R: Integer; SCompare: TStringListSortCompare);
var I, J, P, Tmp: Integer;
begin
  repeat
    I := L;
    J := R;
    P := (L+R) shr 1;
    repeat
      while SCompare(Self,I,P)<0 do Inc(I);
      while SCompare(Self,J,P)>0 do Dec(J);
      if I <= J then begin
        Tmp := integer(fListObj[I]);
        fListObj[I] := fListObj[J];
        fListObj[J] := pointer(Tmp);
        Tmp := integer(FListStr[I]);
        integer(FListStr[I]) := integer(FListStr[J]);
        integer(FListStr[J]) := Tmp;
        if P=I then
          P := J else
        if P=J then
          P := I;
        Inc(I);
        Dec(J);
      end;
    until I>J;
    if L<J then QuickSort(L,J,SCompare);
    L := I;
  until I>=R;
end;

procedure TStringList.SetSorted(Value: Boolean);
begin
  if FSorted <> Value then begin
    if Value then
      Sort;
    FSorted := Value;
  end;
end;

function StringListCompareStrings(List: TStringList; Index1, Index2: Integer): Integer;
begin
  Result := List.CompareStrings(List.fListStr[Index1],List.fListStr[Index2]);
end;

procedure TStringList.Sort;
begin
  CustomSort(StringListCompareStrings);
end;

procedure TStringList.CustomSort(Compare: TStringListSortCompare);
begin
  if (self=nil) or (FCount<=1) then
    exit;
  QuickSort(0,FCount-1,Compare);
end;

function TStringList.CompareStrings(const S1, S2: string): Integer;
begin
  if CaseSensitive then
    Result := AnsiCompareStr(S1, S2) else
    Result := AnsiCompareText(S1, S2);
end;

wp_xyz
Beiträge: 5245
Registriert: Fr 8. Apr 2011, 09:01

Re: Zeilenweise Ausgabe optimieren...

Beitrag von wp_xyz »

Hier ein Speed-Test für verschiedene Sortier-Optionen. Es werden zunächst 200.000 zufällige Strings in einer Stringlist gespeichert. In den folgenden Tests werden diese Strings immer wieder in eine "frische" Stringlist eingefügt und unter verschiedenen Bedingungen sortiert. Bedingungen sind: wann erfolgt die Sortierung, welche String-Vergleichs-Funktion wird verwendet (case-sensitive, use locale), wird die Stringlist zu Beginn schon auf die Endzahl der Einträge dimensioniert (Capacity = N), oder wird die Listengröße beim Überschreiten der bisherigen Größe verdoppelt (Capacity = 0)?
- 1. Test: Zu Beginn gleich Sorted := true setzen. Damit wird jeder String beim Einfügen gleich richtig einsortiert.
- 2. Test: Die Strings werden (mit Sorted = false) in die Zielliste eingefügt, und am Ende wird Sorted auf true gesetzt
- 3. Test: genauso, nur wird statt Sorted = true manuell die Sort-Methode aufgerufen
- 4. Test: genauso, nur wird statt Sort die CustomSort-Methode aufgerufen, einmal mit CompareStr und einmal mit AnsiCompareStr
- 5. Test: genauso, nur wird statt CustomSort deine StringHelper-Sortierung aufgerufen.

Ergebnisse:

Code: Alles auswählen

Creating 200.000 test strings --> 0.036 secs

Capacity = 0

Insert sorted (case-sensitive: yes, use locale: yes) --> 6.499 secs
Insert sorted (case-sensitive: no,  use locale: yes) --> 6.536 secs
Insert sorted (case-sensitive: no,  use locale: no ) --> 6.133 secs

Insert unsorted, set Sorted to true at end (case-sensitive: yes, use locale: yes) --> 0.820 secs
Insert unsorted, set Sorted to true at end (case-sensitive: no,  use locale: yes) --> 0.793 secs
Insert unsorted, set Sorted to true at end (case-sensitive: no,  use locale: no ) --> 0.080 secs

Insert unsorted, call Sort() at end (case-sensitive: yes, use locale: yes) --> 0.768 secs
Insert unsorted, call Sort() at end (case-sensitive: no,  use locale: yes) --> 0.767 secs
Insert unsorted, call Sort() at end (case-sensitive: no,  use locale: no ) --> 0.079 secs

Insert unsorted, call CustomSort(@CompareStr) at end --> 0.176 secs
Insert unsorted, call CustomSort(@AnsiCompareStr) at end --> 0.885 secs

Insert unsorted, call helper for sorting at end  --> 0.129 secs

Press ENTER to close...
Am schnellsten sind Sorted=true und Sort nach dem Einfügen, wenn die Strings "pur" verglichen werden (keine Groß/Kleinschreibung, keine Berücksichtigung von Ländereigenheiten), gefolgt von deinem StringList-Helper. Abgeschlagen die Idee, die Strings schon beim Einlesen zu sortieren.

Die Vordimensionierung der Listengröße hat überraschenderweise keinen messbaren Effekt.

Code: Alles auswählen

program StringList_Speed;
uses
  SysUtils, Classes;

type
  TStringCompareFunc = function(const A, B: String): Integer;

  TStringListHelper = class helper for TStringList
    procedure QuickSortFast;
  end;

function CompareStringsFast(const TextA, TextB: String): Integer;
begin
  // Schneller, bin_aerer Vergleich (ohne Gro_sz-/Kleinschreibung zu ignorieren)
  Result := CompareStr(TextA, TextB);
end;

procedure QuickSortSL(Strings: TStringList; LeftIndex, RightIndex: INTEGER;
  CompareFunc: TStringCompareFunc);
var
  IndexLeft, IndexRight: integer;
  Pivot, Temp: String;
begin
  IndexLeft := LeftIndex;
  IndexRight := RightIndex;
  Pivot := Strings[(LeftIndex + RightIndex) DIV 2];
  repeat
    while CompareFunc(Strings[IndexLeft], Pivot) < 0 do inc(IndexLeft);
    while CompareFunc(Strings[IndexRight], Pivot) > 0 do dec(IndexRight);
    if IndexLeft <= IndexRight then
    begin
      Temp := Strings[IndexLeft];
      Strings[IndexLeft] := Strings[IndexRight];
      Strings[IndexRight] := Temp;
      inc(IndexLeft);
      dec(IndexRight);
    end;
  until IndexLeft > IndexRight;
  if LeftIndex < IndexRight then
    QuickSortSL(Strings, LeftIndex, IndexRight, CompareFunc);
  if IndexLeft < RightIndex then
    QuickSortSL(Strings, IndexLeft, RightIndex, CompareFunc);
end;

procedure TStringListHelper.QuickSortFast;
begin
  if Self.Count > 1 then
    QuickSortSL(Self, 0, Self.Count - 1, @CompareStringsFast);
end;

function StringList_AnsiCompareStr(List: TStringList; Index1, Index2: Integer): Integer;
begin
  Result := AnsiCompareStr(List[Index1], List[Index2]);
end;

function StringList_CompareStr(List: TStringList; Index1, Index2: Integer): Integer;
begin
  Result := CompareStr(List[Index1], List[Index2]);
end;

function RandomString(ALength: Integer): String;
var
  i: Integer;
begin
  SetLength(Result, ALength);
  Result[1] := char(ord('A') + Random(26));
  for i := 2 to ALength do
    Result[i] := char(ord('a') + Random(26));
end;

const
  N = 200*1000;
  CAPACITY = 0; //N;
var
  t: TDateTime;
  L, L1: TStringList;
  i: Integer;
begin
  L1 := TStringList.Create;
  try
    Write('Creating ', Format('%.n', [1.0*N]), ' test strings');
    t := Now;
    for i := 1 to N do
      L1.Add(RandomString(5 + Random(20)));
    t := Now-t;
    WriteLn(' --> ', FormatDateTime('s.zzz', t), ' secs');

    WriteLn;
    WriteLn('Capacity = ', CAPACITY);
    WriteLn;

    Write('Insert sorted (case-sensitive: yes, use locale: yes)');
    L := TStringList.Create;
    try
      L.Capacity := CAPACITY;
      L.CaseSensitive := true;
      L.UseLocale := true;
      L.Sorted := true;
      t := Now;
      for i := 0 to L1.Count-1 do
        L.Add(L1[i]);
      t := Now - t;
      WriteLn(' --> ', FormatDateTime('s.zzz', t), ' secs');
    finally
      L.Free;
    end;

    Write('Insert sorted (case-sensitive: no,  use locale: yes)');
    L := TStringList.Create;
    try
      L.Capacity := CAPACITY;
      L.CaseSensitive := false;
      L.UseLocale := true;
      L.Sorted := true;
      t := Now;
      for i := 0 to L1.Count-1 do
        L.Add(L1[i]);
      t := Now - t;
      WriteLn(' --> ', FormatDateTime('s.zzz', t), ' secs');
    finally
      L.Free;
    end;

    Write('Insert sorted (case-sensitive: no,  use locale: no )');
    L := TStringList.Create;
    try
      L.Capacity := CAPACITY;
      L.CaseSensitive := false;
      L.UseLocale := false;
      L.Sorted := true;
      t := Now;
      for i := 0 to L1.Count-1 do
        L.Add(L1[i]);
      t := Now - t;
      WriteLn(' --> ', FormatDateTime('s.zzz', t), ' secs');
    finally
      L.Free;
    end;

    WriteLn;

    Write('Insert unsorted, set Sorted to true at end (case-sensitive: yes, use locale: yes)');
    L := TStringList.Create;
    try
      L.Capacity := CAPACITY;
      L.CaseSensitive := true;
      L.UseLocale := true;
      t := Now;
      for i := 0 to L1.Count-1 do
        L.Add(L1[i]);
      L.Sorted := true;
      t := Now - t;
      WriteLn(' --> ', FormatDateTime('s.zzz', t), ' secs');
    finally
      L.Free;
    end;

    Write('Insert unsorted, set Sorted to true at end (case-sensitive: no,  use locale: yes)');
    L := TStringList.Create;
    try
      L.Capacity := CAPACITY;
      L.CaseSensitive := false;
      L.UseLocale := true;
      t := Now;
      for i := 0 to L1.Count-1 do
        L.Add(L1[i]);
      L.Sorted := true;
      t := Now - t;
      WriteLn(' --> ', FormatDateTime('s.zzz', t), ' secs');
    finally
      L.Free;
    end;

    Write('Insert unsorted, set Sorted to true at end (case-sensitive: no,  use locale: no )');
    L := TStringList.Create;
    try
      L.Capacity := CAPACITY;
      L.CaseSensitive := false;
      L.UseLocale := false;
      t := Now;
      for i := 0 to L1.Count-1 do
        L.Add(L1[i]);
      L.Sorted := true;
      t := Now - t;
      WriteLn(' --> ', FormatDateTime('s.zzz', t), ' secs');
    finally
      L.Free;
    end;

    WriteLn;

    Write('Insert unsorted, call Sort() at end (case-sensitive: yes, use locale: yes)');
    L := TStringList.Create;
    try
      L.Capacity := CAPACITY;
      L.CaseSensitive := true;
      L.UseLocale := true;
      t := Now;
      for i := 0 to L1.Count-1 do
        L.Add(L1[i]);
      L.Sort;
      t := Now - t;
      WriteLn(' --> ', FormatDateTime('s.zzz', t), ' secs');
    finally
      L.Free;
    end;

    Write('Insert unsorted, call Sort() at end (case-sensitive: no,  use locale: yes)');
    L := TStringList.Create;
    try
      L.Capacity := CAPACITY;
      L.CaseSensitive := false;
      L.UseLocale := true;
      t := Now;
      for i := 0 to L1.Count-1 do
        L.Add(L1[i]);
      L.Sort;
      t := Now - t;
      WriteLn(' --> ', FormatDateTime('s.zzz', t), ' secs');
    finally
      L.Free;
    end;

    Write('Insert unsorted, call Sort() at end (case-sensitive: no,  use locale: no )');
    L := TStringList.Create;
    try
      L.Capacity := CAPACITY;
      L.CaseSensitive := false;
      L.UseLocale := false;
      t := Now;
      for i := 0 to L1.Count-1 do
        L.Add(L1[i]);
      L.Sort;
      t := Now - t;
      WriteLn(' --> ', FormatDateTime('s.zzz', t), ' secs');
    finally
      L.Free;
    end;

    WriteLn;

    Write('Insert unsorted, call CustomSort(@CompareStr) at end');
    L := TStringList.Create;
    try
      L.Capacity := CAPACITY;
      t := Now;
      for i := 0 to L1.Count-1 do
        L.Add(L1[i]);
      L.CustomSort(@StringList_CompareStr);
      t := Now - t;
      WriteLn(' --> ', FormatDateTime('s.zzz', t), ' secs');
    finally
      L.Free;
    end;

    Write('Insert unsorted, call CustomSort(@AnsiCompareStr) at end');
    L := TStringList.Create;
    try
      L.Capacity := CAPACITY;
      t := Now;
      for i := 0 to L1.Count-1 do
        L.Add(L1[i]);
      L.CustomSort(@StringList_AnsiCompareStr);
      t := Now - t;
      WriteLn(' --> ', FormatDateTime('s.zzz', t), ' secs');
    finally
      L.Free;
    end;

    WriteLn;

    Write('Insert unsorted, call helper for sorting at end ');
    L := TStringList.Create;
    try
      L.Capacity := CAPACITY;
      t := Now;
      for i := 0 to L1.Count-1 do
        L.Add(L1[i]);
      L.QuickSortFast;
      t := Now - t;
      WriteLn(' --> ', FormatDateTime('s.zzz', t), ' secs');
    finally
      L.Free;
    end;

  finally
    L1.Free;
  end;

  WriteLn;
  Write('Press ENTER to close...');
  ReadLn;
end. 

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

Re: Zeilenweise Ausgabe optimieren...

Beitrag von alfware17 »

@wp_xyz: vielen Dank, das hilft mir enorm weiter bei meinen Überlegungen und Tests.

@m.fuchs: ich habe keine Ahnung, was deine Entscheidung zu dem genannten Beitrag ausgelöst hat - nur Vermutungen.
Daher meine aufrichtige Entschuldigung, falls ich
- meinen Thread selbst umgebogen habe, andere sind viel schlimmer und es war doch ein zur Überschrift verwandtes/abgeleitetes Thema
- jemanden auf den Schlips getreten habe mit dem Satz, daß euch allen klar ist, was für mich die Entdeckung des Tages darstellte
- die KI erwähnt und teilweise zitiert habe, Die Unit ist übrigens meine eigene, ich hatte nur Hilfe/Anstoß bzw habe meinen Sort vom StringArray wiederverwendet

Ich möchte hier nicht mehr weiter kommentieren und werde auch keine Ergebnisse mehr schreiben,

Benutzeravatar
m.fuchs
Lazarusforum e. V.
Beiträge: 2844
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: Zeilenweise Ausgabe optimieren...

Beitrag von m.fuchs »

alfware17 hat geschrieben: @m.fuchs: ich habe keine Ahnung, was deine Entscheidung zu dem genannten Beitrag ausgelöst hat - nur Vermutungen.
Ich weiß jetzt nicht genau, was du mit der Entscheidung meinst, deine Beiträge sind ja alle da und unverändert. Ich habe dir nur einen Hinweis gegeben, wie schon gesagt: irgendwelche negativen Auswirkungen hat das nicht auf dich - das wäre ja auch unsinnig.
0118999881999119725-3

Software, Bibliotheken, Vorträge und mehr: https://www.ypa-software.de

Antworten