Re: [fpc-pascal] How to avoid Copy

2023-12-30 Thread Sven Barth via fpc-pascal
Amir via fpc-pascal  schrieb am Sa., 30.
Dez. 2023, 08:11:

>
>
> On Dec 29, 2023 9:50 PM, Adriaan van Os  wrote:
>
> Amir--- via fpc-pascal wrote:
> > Hi all,
> >
> >  I have a List of record, where the record has a WideString field.
> >   I have some code like the following:
> >
> > function check(constref v: TMyRecord; data: TListOfMyRecord): Boolean;
> > var
> >   r: TMyRecord;
> >
> > begin
> >   Result := False;
> >   for r in data do
> > if r.State = v.State then
> >   Exit(True);
> > end;
> >
> > I call this method a lot and the CPU profiling shows a lot of cpu time
> > spent on "fpc_copy_proc" (which I assume is doing the deep copy on
> > records) from "TCustomListEnumerator.GetCurrent".
> > I considered other alternatives like using enumerators but they all need
> > a to return a record (and hence copying the widestring field).
> > I can think of two solutions to get rid of the wasting(!) so much time
> > on "fpc_copy_proc":
> > 1) Changing the TMyRecord to TMyClass. But then I need to Create and
> > Free a "lot" of objects.
> > 2) Update TListOfMyRecord to TListOfPointerToMyRecord. This requires a
> > "lot" of memory allocation/fragmentation.
> >
> > Is there a better solution?
>
> Pass the data parameter by reference.
>
> This means I need to have a ListOfMyRecord and a ListOfConstRefMyRecord,
> right?
>

No, that's not a thing.

You simply need to declare your "data" parameter as "constref" or "const"
as well, just like your "v" parameter.

Note: prefer the use of "const" instead of "constref" unless you really
need a reference, because the compiler will then pick the optimal way to
pass the value (e.g. small ones will be passed by register instead of as an
address).

Regards,
Sven

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


Re: [fpc-pascal] How to avoid Copy

2023-12-30 Thread Michael Van Canneyt via fpc-pascal



On Fri, 29 Dec 2023, Amir via fpc-pascal wrote:




On Dec 29, 2023 9:50 PM, Adriaan van Os  wrote:

  Amir--- via fpc-pascal wrote:
  > Hi all,
  >
  >  I have a List of record, where the record has a WideString field.
  >   I have some code like the following:
  >
  > function check(constref v: TMyRecord; data: TListOfMyRecord): Boolean;
  > var
  >   r: TMyRecord;
  >
  > begin
  >   Result := False;
  >   for r in data do
  > if r.State = v.State then
  >   Exit(True);
  > end;
  >
  > I call this method a lot and the CPU profiling shows a lot of cpu time
  > spent on "fpc_copy_proc" (which I assume is doing the deep copy on
  > records) from "TCustomListEnumerator.GetCurrent".
  > I considered other alternatives like using enumerators but they all need
  > a to return a record (and hence copying the widestring field).
  > I can think of two solutions to get rid of the wasting(!) so much time
  > on "fpc_copy_proc":
  > 1) Changing the TMyRecord to TMyClass. But then I need to Create and
  > Free a "lot" of objects.
  > 2) Update TListOfMyRecord to TListOfPointerToMyRecord. This requires a
  > "lot" of memory allocation/fragmentation.
  >
  > Is there a better solution?

  Pass the data parameter by reference.

This means I need to have a ListOfMyRecord and a ListOfConstRefMyRecord, right?


It means you use 
constref  data: TListOfMyRecord
or 
var data: TListOfMyRecord


And try to avoid "for r in data" because it will create a copy for each element
in the list.

I don't know how you defined TListOfMyRecord, but if it is a
generic TList, better change it to a TArray or Array
of TMyRecord, in which case you can use a pointer to the consecutive records
in the array. Generics are convenient, but slow.

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