Hi,


(1) A record is not a pointer. So that would require some implicit referencing in the property

(2) If it was managed, it would be an allocation, so I don't understand this.


I am talking about replacing interfaces with an record.

For example this

/////////////////////////////////////

type ITest = interface
  procedure println;
end;
TTest = class(TInterfacedObject, ITest)
  v: integer;
  constructor Create(av: integer);
  procedure println;
end;

constructor TTest.Create(av: integer);
begin
  v := av;
end;

procedure TTest.println;
begin
  writeln(v);
end;

var c: ITest;
begin
  c := TTest.Create(123);
  c.println;
/////////////////////////////////


would become:


/////////////////////////////////

type

TTestRec = class
  rc: Integer;
  v: integer;
  constructor Create(av: integer);
  procedure println;
end;
RTest = record
  ptr: TTestRec;
  procedure println; inline;
  class operator :=(c: TTestRec): RTest;
  class operator Initialize(var aRec: RTest);
  class operator finalize(var aRec: RTest);
  class operator AddRef(var aRec: RTest);
end;

constructor TTestRec.Create(av: integer);
begin
  v := av;
end;

procedure TTestRec.println;
begin
  writeln(v);
end;

procedure RTest.println;
begin
  ptr.println; //the wrapper function is inlined
end;

class operator RTest.:=(c: TTestRec): RTest;
begin
  result := default(RTest);
  result.ptr := c;
  if c <> nil then
    InterlockedIncrement(c.rc);
end;

class operator RTest.Initialize(var aRec: RTest);
begin
  aRec.ptr := nil;
end;

class operator RTest.finalize(var aRec: RTest);
begin
  if aRec.ptr <> nil then
    if InterlockedDecrement(aRec.ptr.rc) = 0 then
      aRec.ptr.Free;
end;

class operator RTest.AddRef(var aRec: RTest);
begin
  if aRec.ptr <> nil then
    InterlockedIncrement(aRec.ptr.rc);
end;

var
    r: RTest;
begin
  r := TTestRec.Create(123);
  r.println;
/////////////////////////////////////////////////////////

Or even replace the class with a record, too:


/////////////////////////////////////////////////////////

type
PTestRec2 = ^TTestRec2;
TTestRec2 = record
  rc: Integer;
  v: integer;
  class function Create(av: integer): PTestRec2; static;
  procedure println;
end;
RTest2 = record
  ptr: ^TTestRec2;
  procedure println; inline;
  class operator :=(c: PTestRec2): RTest2;
  class operator Initialize(var aRec: RTest2);
  class operator finalize(var aRec: RTest2);
  class operator AddRef(var aRec: RTest2);
end;

class function TTestRec2.Create(av: integer): PTestRec2;
begin
  new(result);
  result^.rc := 0;
  result^.v := av;
end;

procedure TTestRec2.println;
begin
  writeln(v);
end;

procedure RTest2.println;
begin
  ptr^.println;
end;

class operator RTest2.:=(c: PTestRec2): RTest2;
begin
  result := default(RTest2);
  result.ptr := c;
  if c <> nil then
    InterlockedIncrement(c^.rc);
end;

class operator RTest2.Initialize(var aRec: RTest2);
begin
  aRec.ptr := nil;
end;

class operator RTest2.finalize(var aRec: RTest2);
begin
  if aRec.ptr <> nil then
    if InterlockedDecrement(aRec.ptr^.rc) = 0 then
      dispose(aRec.ptr);
end;

class operator RTest2.AddRef(var aRec: RTest2);
begin
  if aRec.ptr <> nil then
    InterlockedIncrement(aRec.ptr^.rc);
end;
var
    r2: RTest2;
begin
  r2 := TTestRec2.Create(123);
  r2.println;
/////////////////////////////////////////////////////////




Not sure if it is actually faster. That needs to be investigated.

But it definitely helps with the memory usage:

  writeln(ttest.InstanceSize);
  writeln(ttestrec.InstanceSize);
  writeln(sizeof(ttestrec2));

40
16
8

With many small objects it should be faster just because it fits better in the cache.

Cheers,
Benito
On 17.02.21 14:31, Marco van de Voort via fpc-pascal wrote:

Op 2021-02-17 om 00:02 schreef Benito van der Zander via fpc-pascal:

And there often is a lot of unintentional deep copying. This is also why a property returning a record is fairly useless except for extremely small records like TPoint (and even that is not optimal no

But a managed record to replace an interface, would only contain a single pointer/class ref. That can be copied fast

(1) A record is not a pointer. So that would require some implicit referencing in the property

(2) If it was managed, it would be an allocation, so I don't understand this.


_______________________________________________
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
_______________________________________________
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal

Reply via email to