Base de Conhecimento

Smartpointers em Delphi

Como você sabe, a Delphi não tem um coletor de lixo. O ARC logo será removido do compilador sem janelas. Portanto, a Delphi não tem estrutura para liberar objetos automaticamente. Fizemos algumas pesquisas para ver se os Smartpointers são adequados para a liberação automática de objetos. O conceito de Smartpointers é emprestado do C++ e foi introduzido pela primeira vez na Delphi por Barry Kelly. A estrutura da Spring4D também tem uma implementação de Smartpointers.

Para mostrar um exemplo do uso de Smartpointers, vamos dar uma olhada em algum código:

var
  s: TStringList;
begin
  s := TStringList.Create;
try
  DoSomething(s);
finally
  s.Free;
end;

Com os Smartpointers, o código será parecido com este:

var
  s: IShared<TStringlist>;
begin
  s := Shared.Make(TStringList.Create);
  DoSomething(s);
end;

Escrevemos um programa de teste para testar um cenário mais complexo. Aqui está o código do programa de teste:

program TestSmartPointer;

{$APPTYPE CONSOLE}

uses
  Spring,
  Diagnostics,
  Classes,
  SysUtils,
  System.Generics.Collections;

type
  TTestObj = class
  private
    FDescription: string;
  public
    property Description: string read FDescription write FDescription;
    destructor Destroy; override;
  end;

  TTestList = class(TList<IShared<TTestObj>>)
  public
    destructor Destroy; override;
  end;

procedure Test_SmartPointer;
var
  lTestList: IShared<TTestList>;
  lTestObj: IShared<TTestObj>;
  i: integer;
begin
  writeln('SmartPointer test started');
  lTestList := Shared.Make(TTestList.Create);
  for i := 1 to 10 do
  begin
    lTestObj := Shared.Make(TTestObj.Create);
    lTestObj.Description := i.ToString;
    writeln(format('TestObj with description %s added to Testlist', [lTestObj.Description]));
    lTestList.Add(lTestObj);
  end;
  
  for lTestObj in lTestList do
    writeln(format('Item %d of Testlist has value %s', lTestList.IndexOf(lTestObj), lTestObj.Description));

  writeln('SmartPointer test finished');
end;

{ TTestObj }

destructor TTestObj.Destroy;
begin
  writeln(format('TestObj with description %s is destroyed', [FDescription]));
  inherited;
end;

{ TTestList }

destructor TTestList.Destroy;
begin
  writeln('TTestList is destroyed');
  inherited;
end;

begin
  Test_SmartPointer;
  readln;
end.

Neste programa, uma lista genérica TTestList é preenchida com objetos TTestObj. Observe a declaração da Lista TTestList:

TTestList = class(TList<IShared<TTestObj>>)

A saída deste programa de teste está na figura abaixo.

Como você pode ver, os objetos são liberados após a linha “Teste SmartPointer terminado”. Assim, quando o procedimento Test_SmartPointer é finalizado, as variáveis locais saem do escopo e são automaticamente liberadas. Isto funciona bem.
Também testamos o desempenho e a memória utilizada. Os resultados são os seguintes:

No teste de velocidade foram criadas 100.000 listas e cada lista foi preenchida com 100 itens. Os smartpointers são 29,17% mais lentos do que quando a técnica clássica é utilizada.
No teste de memória 1 a lista foi criada com 100.000 itens. Quando a lista foi totalmente preenchida, a memória utilizada pelo programa foi medida. Os smartpointers usam 26,94% mais memória do que quando a técnica clássica é usada. Isto são diferenças consideráveis.

Conclusão

Smartpointers funcionam tecnicamente bem. Os objetos são liberados conforme o esperado. No entanto, há uma desvantagem considerável quando se trata de velocidade e memória usada. Além disso, todo objeto deve ser declarado com IShared<object> e criado com Shared.Make(object.create). Nossa recomendação de smartpointers é que é um pouco demais em desempenho e código para ser usado como uma estrutura geral fácil de usar para liberar objetos automaticamente no Delphi.

References:

https://blog.marcocantu.com/blog/2018-october-Delphi-ARC-directions.html

http://blog.barrkel.com/2008/09/smart-pointers-in-delphi.html

https://delphisorcery.blogspot.com/2015/01/smart-pointers-in-delphi.html

https://en.delphipraxis.net/topic/402-smart-pointers-generics-vrs-non-generic-implementastion/

 

Contato

Deixe-nos ajudá-lo a realizar seus sonhos.