delphidelphi-xe7

TMemo is painfuly slow when working with large number of lines


Experiment:

I have 100000 lines in a TMemo. I want to do something like:

 for i:= 0 to Memo.Lines.Count-1 do
  Memo.Lines[i]:= SomeTrim(Memo.Lines[i]);

but the speed is 0.5 lines per second!!

After adding BeginUpdate/EndUpdate I don't see any speed improvement.

 Memo.Lines.BeginUpdate;
 for i:= 0 to Memo.Lines.Count-1 do
  Memo.Lines[i]:= SomeTrim(Memo.Lines[i]);
 Memo.Lines.EndUpdate;

My question is why BeginUpdate/EndUpdate won't help?


Solution

  • TStrings.BeginUpdate/EndUpdate will only prohibit the OnChanging and OnChanged events. It has no influence on the internal handling of the changes to the content itself.

    TMemo.Lines is implemented by TMemoStrings which stores the text content in the Window control itself. Thus BeginUpdate/EndUpdate is pretty useless here.

    You might get better results by using a local TStringList instance, and using the Text property to copy the data from TMemo to TStringList and back. The Text property is the most efficient way to access the whole content of a TMemo at once.

      lst := TStringList.Create;
      try
        lst.Text := Memo1.Lines.Text;
        for I := 0 to lst.Count - 1 do begin
          lst[I] := SomeTrim(lst[I]);
        end;
        Memo1.Lines.Text := lst.Text;
      finally
        lst.Free;
      end;
    

    Note: Some comments mention to use Assign instead of the Text property when copying the content from and to the Memo: Assign is significantly slower in this case due to an internal optimization of the Text property for TMemoLines. The Getter and Setter of this property accesses directly the Windows control with a single WM_GETTEXT/WM_SETTEXT message, while Assign uses one EM_GETLINE message per line for reading and a sequence of EM_LINEINDEX, EM_SETSEL, EM_LINELENGTH and EM_REPLACESEL per line for writing. A simple timing test shows that the above code needs about 600 ms while replacing the Text assignments with Assign calls needs more than 11 seconds!