Поясните результаты

Вопросы программирования на Free Pascal, использования компилятора и утилит.

Модератор: Модераторы

Поясните результаты

Сообщение Brainenjii » 24.12.2012 10:00:57

Накидал маленький класс для формирования строк. Почему вариант с одним объектом работает настолько (на 100%-300%) медленней, чем с пересозданием объектов?
Код: Выделить всё
program Project1;

Uses
  Classes, sysutils, strutils;

Type

{ TFormatterClass }

TFormatterClass = Class
  Type

  { TFormatterParamClass }

TFormatterParamClass = Class
    Private
      bName: String;
      bValue: String;
    Public
      Property Name: String Read bName;
      Property Value: String Read bValue;
      Constructor Build(aName: String; Const aValue: String);
      Constructor Build(aName: String; Const aValue: Integer);
      Constructor Build(aName: String; Const aValue: Double);
      Constructor Build(aName: String; Const aValue: TDateTime;
        Const aFormat: String);
      Destructor Burn;
  End;
  Private
    bParams: TList;
    bString: String;
  Public
    Function Add(Const aName: String;
      Const aValue: String): TFormatterClass; Inline;
    Function Add(Const aName: String;
      Const aValue: Integer): TFormatterClass; Inline;
    Function Add(Const aName: String;
      Const aValue: Double): TFormatterClass; Inline;
    Function Add(Const aName: String; Const aValue: TDateTime;
      Const aFormat: String): TFormatterClass; Inline;

    Function Get(Const aName: String; Const aValue: String;
      Const aBurn: Boolean = TRUE): String; Inline;
    Function Get(Const aName: String; Const aValue: Integer;
      Const aBurn: Boolean = TRUE): String; Inline;
    Function Get(Const aName: String; Const aValue: Double;
      Const aBurn: Boolean = TRUE): String; Inline;
    Function Get(Const aName: String; Const aValue: TDateTime;
      Const aFormat: String; Const aBurn: Boolean = TRUE): String; Inline;
    Function Get(Const aBurn: Boolean = TRUE): String;

    Procedure PurgeParams;

    Constructor Build(Const aParamString: String);
    Destructor Burn;
End;

{ TFormatterClass.TFormatterParamClass }

Constructor TFormatterClass.TFormatterParamClass.Build(aName: String;
  Const aValue: String);
Begin
  bName := '{' + aName + '}';
  bValue := aValue;
End;

Constructor TFormatterClass.TFormatterParamClass.Build(aName: String;
  Const aValue: Integer);
Begin
  Build(aName, IntToStr(aValue));
End;

Constructor TFormatterClass.TFormatterParamClass.Build(aName: String;
  Const aValue: Double);
Begin
  Build(aName, FloatToStr(aValue));
End;

Constructor TFormatterClass.TFormatterParamClass.Build(aName: String;
  Const aValue: TDateTime; Const aFormat: String);
Begin
  Build(aName, FormatDateTime(aFormat, aValue));
End;

Destructor TFormatterClass.TFormatterParamClass.Burn;
Begin

End;

{ TFormatterClass }

Function TFormatterClass.Add(Const aName: String; Const aValue: String
  ): TFormatterClass;
Begin
  Result := Self;
  bParams.Add(TFormatterParamClass.Build(aName, aValue));
End;

Function TFormatterClass.Add(Const aName: String; Const aValue: Integer
  ): TFormatterClass;
Begin
  Result := Self;
  bParams.Add(TFormatterParamClass.Build(aName, aValue));
End;

Function TFormatterClass.Add(Const aName: String; Const aValue: Double
  ): TFormatterClass;
Begin
  Result := Self;
  bParams.Add(TFormatterParamClass.Build(aName, aValue));
End;

Function TFormatterClass.Add(Const aName: String; Const aValue: TDateTime;
  Const aFormat: String): TFormatterClass;
Begin
  Result := Self;
  bParams.Add(TFormatterParamClass.Build(aName, aValue));
End;

Function TFormatterClass.Get(Const aName: String; Const aValue: String;
  Const aBurn: Boolean): String;
Begin
  Add(aName, aValue);
  Result := Get(aBurn);
End;

Function TFormatterClass.Get(Const aName: String; Const aValue: Integer;
  Const aBurn: Boolean): String;
Begin
  Add(aName, aValue);
  Result := Get(aBurn);
End;

Function TFormatterClass.Get(Const aName: String; Const aValue: Double;
  Const aBurn: Boolean): String;
Begin
  Add(aName, aValue);
  Result := Get(aBurn);
End;

Function TFormatterClass.Get(Const aName: String; Const aValue: TDateTime;
  Const aFormat: String; Const aBurn: Boolean): String;
Begin
  Add(aName, aValue);
  Result := Get(aBurn);
End;

Function TFormatterClass.Get(Const aBurn: Boolean): String;
Var
  i: Integer;
  aParam: TFormatterParamClass;
Begin
  Result := bString;
  For i := 0 To bParams.Count - 1 Do
    Begin
      aParam := TFormatterParamClass(bParams[i]);
      Result := StringsReplace(Result, aParam.Name, aParam.Value,
        [rfReplaceAll]);
    End;
  If aBurn Then Burn;
End;

Procedure TFormatterClass.PurgeParams;
Var
  i: Integer;
Begin
  For i := 0 To bParams.Count - 1 Do
    TFormatterParamClass(bParams[i]).Burn;
  bParams.Clear;
End;

Constructor TFormatterClass.Build(Const aParamString: String);
Begin
  bParams := TList.Create;
  bString := aParamString;
End;

Destructor TFormatterClass.Burn;
Begin
  PurgeParams;
  bParams.Free;
End;

Function Formatter(Const aParamString: String): TFormatterClass;
Begin
  Result := TFormatterClass.Build(aParamString);
End;

Var
  i: Integer;
  aStart: TDateTime;
  aString: String;
  aFormatter: TFormatterClass;
begin
  aStart := Now;
  For i := 0 To 10000 Do
    aString := Formatter('{Hello} {World}').Add('Hello', 'Не работает').
      Get('World', 'нихчего!!!');
  WriteLn('Many formatters: ', FormatDateTime('ss:zz', Now - aStart)); //<- Many formatters: 00:055

  aStart := Now;
  aFormatter := TFormatterClass.Build('{Hello} {World}');
  For i := 0 To 10000 Do
    Begin
      aString := aFormatter.Add('Hello', 'Не работает').
        Get('World', 'нихчего!!!', FALSE);
      aFormatter.PurgeParams;
    End;
  aFormatter.Burn;
  WriteLn('One formatter: ', FormatDateTime('ss:zz', Now - aStart)); //<- One formatter: 00:213

  aStart := Now;
  For i := 0 To 10000 Do
    Begin
      aString += Format('%s %s', ['Не работает', 'нихчего!!!']);
      If i div 100 = 0 Then aString := '';
    End;
  WriteLn('Format: ', FormatDateTime('ss:zz', Now - aStart)); //<- Format: 00:021
end.

Это как-то противоречит всем моим представлениям об накладных расходах ^_^
Аватара пользователя
Brainenjii
энтузиаст
 
Сообщения: 1351
Зарегистрирован: 10.05.2007 00:04:46

Re: Поясните результаты

Сообщение Sergei I. Gorelkin » 24.12.2012 12:44:05

Возможно, возникает ситуация наподобие этой: http://bugs.freepascal.org/view.php?id=18079
Если выделять попеременно куски памяти двух определенных размеров, менеджер памяти может сказать "меня тут больше нет".
Аватара пользователя
Sergei I. Gorelkin
энтузиаст
 
Сообщения: 1407
Зарегистрирован: 24.07.2005 14:40:41
Откуда: Зеленоград


Вернуться в Free Pascal Compiler

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 6

Рейтинг@Mail.ru