[fpc-pascal] How to avoid Copy
Michael Van Canneyt
michael at freepascal.org
Sat Dec 30 09:18:36 CET 2023
On Fri, 29 Dec 2023, Amir via fpc-pascal wrote:
>
>
> On Dec 29, 2023 9:50 PM, Adriaan van Os <adriaan at adriaan.biz> 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<TMyRecord>, better change it to a TArray<TMyRecord> 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.
More information about the fpc-pascal
mailing list