Некоторые обычные операции со строками и динамическими массивами можно делать в 100 раз быстрее.

ReplaceStr

Функции замены подстроки AnsiReplaceStr и AnsiReplaceText работают довольно медленно для текстов размером сотни килобайт c тысячами замен подстроки. Узкое место оказалась в медленном сложении строк типа
LongText := LongText + ShortText

В этой операции для новой более длинной строки выделяется необходимое количество памяти. Опыт показал, что обработка текста значительно ускоряется, если выделять память не тысячи раз, а всю память заранее, или всего несколько раз. Так работает выделнение памяти в классе TList , но в AnsiReplaceStr оптимизация выделения памяти не используется.

Сначала создадим отдельный класс для хранения строки.

TWideString = class
private
  FText: WideString;
  LenText: Integer; //index of the last char
  CurrentLenText: Integer; //actual length от FText
  SpareLen: Integer;
  function GetText: WideString;
  procedure SetText(const Text: WideString);
public
  procedure Append(C: WideString);
  property Text: WideString read GetText write SetText;
  property Length:Integer read LenText;
end;

function TWideString.GetText: WideString;
begin
  CurrentLenText := LenText;
  SetLength(FText, CurrentLenText);
  {result}GetText := FText;
end;

procedure TWideString.SetText(const Text: WideString);
begin
  FText := Text;
  LenText := Length(Text);
  CurrentLenText := LenText;
end;

procedure TWideString.Append(C: WideString);
var i, LenC: integer;
begin
  LenC := Length(C);
  if LenText + LenC > CurrentLenText then
  begin
   SpareLen := max(SpareLen, CurrentLenText);
   CurrentLenText := LenText + LenC + SpareLen;
   SetLength(FText, CurrentLenText);
  end;
  for i := 1 to LenC do
  begin
   inc(LenText);
   FText[LenText] := C[i];
  end;
end;

Для поиска подстроки требуется функция PosEx , но в Delphi7 она неправильно работает со строками WideString . Поэтому используем функцию WidePosEx .

function WidePosEx(const SubStr, S: WideString; Offset: Integer): Integer;
var i, X, Len, LenSubStr, Res: Integer;
begin
  if Offset = 1 then Res := Pos(SubStr, S) else
  begin
  i := Offset;
  LenSubStr := Length(SubStr);
  Len := Length(S) - LenSubStr + 1;
  while i <= Len do
  begin
   if S[i] = SubStr[1] then
   begin
    X := 1;
    while (X < LenSubStr) and (S[i + X] = SubStr[X + 1]) do Inc(X);
    if (X = LenSubStr) then
    begin
     Res := i;
     {result}WidePosEx := Res;
     exit;
    end;
   end;
   Inc(i);
  end;
  Res := 0;
  end;
  {result}WidePosEx := Res;
end;

Наконец, можно написать функцию замены подстроки.

function ReplaceStr(const Source, oldStr, newStr: WideString): WideString;
var PosOfOldStr, PosOfNextSearch, LenOldStr: integer; Res: TWideString;
begin
  LenOldStr := Length(oldStr);
  Res := TWideString.Create;
  PosOfNextSearch := 1;
  repeat
   PosOfOldStr := WidePosEx(oldStr, Source, PosOfNextSearch);
   if PosOfOldStr = 0 then break;
   Res.Append(copy(Source, PosOfNextSearch, PosOfOldStr - PosOfNextSearch));
   Res.Append(newStr);
   PosOfNextSearch := PosOfOldStr + LenOldStr;
  until PosOfOldStr = 0;
  //till end of line
  Res.Append(copy(Source, PosOfNextSearch, maxInt));
  {result}ReplaceStr := Res.Text;
  Res.Destroy;
end;

Для тестирования я использовал похожий на xml текст размером 1Мб.

//usual making long text
t0 := Time;
for i := 1 to 50000 do txt := txt + 'A1="2345" ';
dt0 := Time - t0;
//usual change of substring
t0 := Time;
txt := AnsiReplaceStr(txt, '23', '67');
dt1 := Time - t0;
//fast algorithm
t0 := Time;
txt := ReplaceStr(txt, '45', '89');
dt2 := Time - t0;

В этом примере на моём РС получилось
dt0 = 41 секунда
dt1 = 59 секунд
dt2 = 0.1 секунды

Теперь ясно, что самый обычный способ создания текста в цикле
txt := txt + 'A1="2345" '
медленный, и его можно было бы ускорить, используя TWideString . Также можно ускорить функцию RemoveCrLfTabDSpace.