Delphi loop speed question

delphi, for-loop, loops, performance

Solution

OK. I have tried to optimize your code. For final tests, some test-data is needed.

What I have done (it include most of the ideas from Mason):

- comment out the code about "cancel" and "

- gave types and variables a more meaningfull name

- used the names that Delphi uses ("Application" in stead of "application", etc) to make it readable

- moved some logic into "KeepUIGoing"

- move the calculation of the suffixes out of the main loop into an initialization loop

- made it optionally use a TStringBuilder (which can be way faster than a TStringList, and is available since Delphi 2009)

Below is the modified code, let me know if it works for you.

procedure TForm2.Button1Click(Sender: TObject);
{$define UseStringBuilder}
  procedure KeepUIGoing(SourceListIndex: Integer);
  begin
    if SourceListIndex mod 100 = 0 then
    begin
      Application.ProcessMessages;
      // so it doesn't freeze the application in long loops.  Not 100% sure where this should be placed, if at all.
      Sleep(1);
    end;
  end;
const
  First = 'a';
  Last = 'z';
type
  TRange = First .. Last;
  TSuffixes = array [TRange, TRange] of string;
var
  OuterIndex, InnerIndex: Char;
  SourceListIndex: Integer;
  SourceList, TargetList: TStrings;
  Suffixes: TSuffixes;
  NewLine: string;
{$ifdef UseStringBuilder}
  TargetStringBuilder: TStringBuilder; // could be way faster than TStringList
{$endif UseStringBuilder}
begin
  for OuterIndex := First to Last do
    for InnerIndex := First to Last do
      Suffixes[OuterIndex, InnerIndex] := OuterIndex + InnerIndex;

  SourceList := TStringList.Create;
  TargetList := TStringList.Create;
{$ifdef UseStringBuilder}
  TargetStringBuilder := TStringBuilder.Create();
{$endif UseStringBuilder}
  try
    SourceList.Text := queuebox.Items.Text;
    for OuterIndex := First to Last do
    begin
      for InnerIndex := First to Last do
      begin
        for SourceListIndex := 0 to SourceList.Count - 1 do
        begin
          KeepUIGoing(SourceListIndex);
          // if cancel then
          // Break;
          NewLine := SourceList.Strings[SourceListIndex] + Suffixes[OuterIndex, InnerIndex];
{$ifdef UseStringBuilder}
          TargetStringBuilder.AppendLine(NewLine);
{$else}
          TargetList.Add(NewLine);
{$endif UseStringBuilder}
        end;
      end;
    end;
{$ifdef UseStringBuilder}
    TargetList.Text := TargetStringBuilder.ToString();
{$endif UseStringBuilder}
    // insertsingle(TargetList, queuebox);
  finally
{$ifdef UseStringBuilder}
    FreeAndNil(TargetStringBuilder);
{$endif UseStringBuilder}
    FreeAndNil(SourceList);
    FreeAndNil(TargetList);
  end;
end;

--jeroen

Problem

Is there a faster way? I basically need to add AA-ZZ to thousands of records at a time. Just a list of 35 items takes quite a while to complete muchless a list of a thousand. ``` procedure Tmainform.btnSeederClick(Sender: TObject); var ch,ch2:char; i:integer; slist1, slist2:TStrings; begin slist1:= TStringList.Create; slist2:= TStringList.Create; slist1.Text :=queuebox.Items.Text; for ch := 'a' to 'z' do begin for ch2 := 'a' to 'z' do begin // for I := 0 to slist1.Count - 1 do begin application.ProcessMessages; // so it doesn't freeze the application in long loops. Not 100% sure where this should be placed, if at all. sleep(1); //Without this it doesn't process the cancel button. if cancel then Break; slist2.Add(slist1.Strings[i]+ch+ch2); end; end; end; insertsingle(slist2,queuebox); freeandnil(slist1); freeandnil(slist2); ``` end; Thanks for any help

Original source