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?
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!