<!DOCTYPE html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  </head>
  <body>
    <br>
    <div class="moz-cite-prefix">On 12/30/23 00:20, Sven Barth via
      fpc-pascal wrote:<br>
    </div>
    <blockquote type="cite"
cite="mid:CAFMUeB8OJMJ8oBcx_62_pwTBiq8sjJMCFXArA0AEAsQhf7DxAA@mail.gmail.com">
      <meta http-equiv="content-type" content="text/html; charset=UTF-8">
      <div dir="auto">
        <div>
          <div class="gmail_quote">
            <div dir="ltr" class="gmail_attr">Amir via fpc-pascal <<a
                href="mailto:fpc-pascal@lists.freepascal.org"
                moz-do-not-send="true" class="moz-txt-link-freetext">fpc-pascal@lists.freepascal.org</a>>
              schrieb am Sa., 30. Dez. 2023, 08:11:<br>
            </div>
            <blockquote class="gmail_quote"
style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
              <div dir="auto">
                <div><br>
                  <div class="gmail_extra"><br>
                    <div class="gmail_quote">On Dec 29, 2023 9:50 PM,
                      Adriaan van Os <<a
                        href="mailto:adriaan@adriaan.biz"
                        target="_blank" rel="noreferrer"
                        moz-do-not-send="true"
                        class="moz-txt-link-freetext">adriaan@adriaan.biz</a>>
                      wrote:<br type="attribution">
                      <blockquote
style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Amir---
                        via fpc-pascal wrote:
                        <br>
                        > Hi all,
                        <br>
                        > <br>
                        >  I have a List of record, where the record
                        has a WideString field.
                        <br>
                        >   I have some code like the following:
                        <br>
                        > <br>
                        > function check(constref v: TMyRecord; data:
                        TListOfMyRecord): Boolean;
                        <br>
                        > var
                        <br>
                        >   r: TMyRecord;
                        <br>
                        > <br>
                        > begin
                        <br>
                        >   Result := False;
                        <br>
                        >   for r in data do
                        <br>
                        >     if r.State = v.State then
                        <br>
                        >       Exit(True);
                        <br>
                        > end;
                        <br>
                        > <br>
                        > I call this method a lot and the CPU
                        profiling shows a lot of cpu time <br>
                        > spent on "fpc_copy_proc" (which I assume is
                        doing the deep copy on <br>
                        > records) from
                        "TCustomListEnumerator.GetCurrent".
                        <br>
                        > I considered other alternatives like using
                        enumerators but they all need <br>
                        > a to return a record (and hence copying the
                        widestring field).
                        <br>
                        > I can think of two solutions to get rid of
                        the wasting(!) so much time <br>
                        > on "fpc_copy_proc":
                        <br>
                        > 1) Changing the TMyRecord to TMyClass. But
                        then I need to Create and <br>
                        > Free a "lot" of objects.
                        <br>
                        > 2) Update TListOfMyRecord to
                        TListOfPointerToMyRecord. This requires a <br>
                        > "lot" of memory allocation/fragmentation.
                        <br>
                        > <br>
                        > Is there a better solution?
                        <br>
                        <br>
                        Pass the data parameter by reference.</blockquote>
                    </div>
                  </div>
                </div>
                <div dir="auto">This means I need to have a
                  ListOfMyRecord and a ListOfConstRefMyRecord, right? </div>
              </div>
            </blockquote>
          </div>
        </div>
        <div dir="auto"><br>
        </div>
        <div dir="auto">No, that's not a thing.</div>
        <div dir="auto"><br>
        </div>
        <div dir="auto">You simply need to declare your "data" parameter
          as "constref" or "const" as well, just like your "v"
          parameter. </div>
      </div>
    </blockquote>
    Have a look at this piece of code (The complete code is attached):<br>
    <font face="monospace">type</font><br>
    <font face="monospace">  TMyRecord = record</font><br>
    <font face="monospace">    Str: AnsiString;</font><br>
    <font face="monospace">    Index: Integer;</font><br>
    <br>
    <font face="monospace">  end;</font><br>
    <font face="monospace">  PMyRecord = ^TMyRecord;</font><br>
    <br>
    <font face="monospace">  TMyList = specialize
      TList<TMyRecord>;</font><br>
    <font face="monospace">  TMyPtrList = specialize
      TList<PMyRecord>;</font><br>
    <br>
    <font face="monospace">function Check1(const MyList: TMyList):
      Integer;</font><br>
    <font face="monospace">var</font><br>
    <font face="monospace">   data: TMyRecord;</font><br>
    <br>
    <font face="monospace">begin</font><br>
    <font face="monospace">  Result := 0;</font><br>
    <font face="monospace">  for data in MyList do</font><br>
    <font face="monospace">    if data.Index mod 100 = 0 then</font><br>
    <font face="monospace">      Inc(Result);</font><br>
    <br>
    <font face="monospace">end;</font><br>
    <br>
    <font face="monospace">function Check2(MyList: TMyList): Integer;</font><br>
    <font face="monospace">var</font><br>
    <font face="monospace">   data: TMyRecord;</font><br>
    <br>
    <font face="monospace">begin</font><br>
    <font face="monospace">  Result := 0;</font><br>
    <font face="monospace">  for data in MyList do</font><br>
    <font face="monospace">    if data.Index mod 100 = 0 then</font><br>
    <font face="monospace">      Inc(Result);</font><br>
    <br>
    <font face="monospace">end;</font><br>
    <br>
    <font face="monospace">function Check3(MyPtrList: TMyPtrList):
      Integer;</font><br>
    <font face="monospace">var</font><br>
    <font face="monospace">   data: PMyRecord;</font><br>
    <br>
    <font face="monospace">begin</font><br>
    <font face="monospace">  Result := 0;</font><br>
    <font face="monospace">  for data in MyPtrList do</font><br>
    <font face="monospace">    if data^.Index mod 100 = 0 then</font><br>
    <font face="monospace">      Inc(Result);</font><br>
    <br>
    <font face="monospace">end;</font><br>
    <br>
    <br>
    I compiled the code with `fpc -O3 -Sd -gv -g -gl ` and ran
    `valgrind` on it (the output is attached). It does not look like
    there is a big difference between the Check1 and Check2 but Check3
    is about 20 times faster than the other two.<br>
    I believe the issue could be resolved if we make
    "TCustomListWithPointers.GetPtrEnumerator" a public method. Then,
    one can implement the following function:<br>
    <br>
    <font face="monospace">function Check4(MyList: TMyList): Integer;</font><br>
    <font face="monospace">....</font><br>
    <font face="monospace">  it := MyList.GetPreEnumerator;</font><br>
    <font face="monospace">  while it.MoveNext do</font><br>
    <font face="monospace">  begin</font><br>
    <font face="monospace">    if it.Current^.Index mod 100 = 0 then</font><br>
    <font face="monospace">     ....</font><br>
    <font face="monospace">  end;</font><br>
     <br>
  </body>
</html>