<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  </head>
  <body smarttemplateinserted="true">
    <div id="smartTemplate4-template">Hi,<br>
      <br>
      <blockquote type="cite"
cite="mid:CAL4d7FjqeUuHLRLni3wtMid3dzbmpbaBHCeqE=rC91jho0AvyQ@mail.gmail.com">
        <div>The trick with enumerators is to never make them classes,
          and use advanced records instead, I've found. This way you
          avoid the heap allocation and the implicit try/finally. Also
          make sure you inline the MoveNext and GetCurrent! </div>
      </blockquote>
    </div>
    <div><br>
    </div>
    <div>that's what I do.</div>
    <div><br>
    </div>
    <div><br>
    </div>
    <div>But the generated assembly is still worse than an old for loop,
      because it keeps all the fields of the record in memory.</div>
    <div><br>
    </div>
    <div>for example<br>
    </div>
    <div><br>
    </div>
    <div>>   for I in TSlice<SizeUInt>.TakeWhile(Arr, Test) do
      J := I;</div>
    <div><br>
    </div>
    <div>generates something like this<br>
    </div>
    <div><br>
    </div>
    <div>0000000000401290 488b45f0                 mov   
      -0x10(%rbp),%rax<br>
      0000000000401294 488b00                   mov    (%rax),%rax<br>
      0000000000401297 488905b22a0300           mov   
      %rax,0x32ab2(%rip)        # 0x433d50 <U_$P$PROJECT1_$$_I><br>
      project1.lpr:75                           J := I;<br>
      000000000040129E 488905bb2a0300           mov   
      %rax,0x32abb(%rip)        # 0x433d60 <U_$P$PROJECT1_$$_J><br>
      project1.lpr:74                           for I in
      TSlice<SizeUInt>.TakeWhile(Arr, Test) do<br>
      00000000004012A5 488345f008               addq   $0x8,-0x10(%rbp)<br>
      project1.lpr:69                           begin<br>
      00000000004012AA 488b45e8                 mov    -0x18(%rbp),%rax<br>
      project1.lpr:74                           for I in
      TSlice<SizeUInt>.TakeWhile(Arr, Test) do<br>
      00000000004012AE 483b45f0                 cmp    -0x10(%rbp),%rax<br>
      00000000004012B2 720a                     jb     0x4012be
      <main+334><br>
      00000000004012B4 483b45e0                 cmp    -0x20(%rbp),%rax<br>
      00000000004012B8 7404                     je     0x4012be
      <main+334><br>
      00000000004012BA b001                     mov    $0x1,%al<br>
      00000000004012BC eb02                     jmp    0x4012c0
      <main+336><br>
      00000000004012BE 30c0                     xor    %al,%al<br>
      00000000004012C0 84c0                     test   %al,%al<br>
      00000000004012C2 75cc                     jne    0x401290
      <main+288><br>
    </div>
    <div><br>
    </div>
    <div>Nearly every line is accessing some memory, when it could keep
      everything in a few registers. amd64 has 16 registers, but fpc
      seems to only know three when records are involved<br>
    </div>
    <div><br>
    </div>
    <br>
    <div><br>
      Cheers,<br>
      Benito </div>
    <br>
    <div class="moz-cite-prefix">Am 22.02.19 um 16:51 schrieb Ben
      Grasset:<br>
    </div>
    <blockquote type="cite"
cite="mid:CAL4d7Fjw5J4L5rM_U_ecEUoqainFDHoNfc9oxWUSs4YjUP-kFA@mail.gmail.com">
      <meta http-equiv="content-type" content="text/html; charset=UTF-8">
      <div dir="ltr">
        <div dir="ltr">
          <div dir="ltr">On Fri, Feb 22, 2019 at 1:07 AM Paul van Helden
            <<a href="mailto:paul@planetgis.co.za"
              moz-do-not-send="true">paul@planetgis.co.za</a>> wrote:<br>
          </div>
          <div class="gmail_quote">
            <blockquote class="gmail_quote" style="margin:0px 0px 0px
              0.8ex;border-left:1px solid
              rgb(204,204,204);padding-left:1ex">
              <div dir="ltr">
                <div class="gmail_quote">
                  <div> How do you make a (for in) enumerator with a
                    record? I don't use them for exactly this reason,
                    and they did seem to be another useful language
                    feature that turned out to be poorly implemented by
                    Embarcadero. (Haven't checked with FPC).</div>
                </div>
              </div>
            </blockquote>
            <div><br>
            </div>
            <div>Here's an example (for FPC) that demonstrates it by
              implementing the "take-while" pattern:</div>
            <div><br>
            </div>
            <div>program TakeWhileExample;</div>
            <div><br>
            </div>
            <div>{$mode Delphi}{$H+}{$J-}</div>
            <div>{$modeswitch NestedProcVars}</div>
            <div>{$ImplicitExceptions Off}</div>
            <div>{$PointerMath On}</div>
            <div><br>
            </div>
            <div>type</div>
            <div>  TSlice<T> = record</div>
            <div>  public type</div>
            <div>    PT = ^T;</div>
            <div>    ArrayType = array of T;</div>
            <div>  private</div>
            <div>    FFirst, FLast, FCurrent: PT;</div>
            <div>    function GetCurrent: T; inline;</div>
            <div>  public</div>
            <div>    function GetEnumerator: TSlice<T>; inline;</div>
            <div>    function MoveNext: Boolean; inline;</div>
            <div>    class function TakeWhile(const A: ArrayType;
              function F(const Val: T): Boolean): TSlice<T>;
              static; inline;</div>
            <div>    property Current: T read GetCurrent;</div>
            <div>  end;</div>
            <div><br>
            </div>
            <div>  TTestFunc<T> = function(const Val: T): Boolean;</div>
            <div><br>
            </div>
            <div>  function TSlice<T>.GetCurrent: T;</div>
            <div>  begin</div>
            <div>    Result := FCurrent^;</div>
            <div>  end;</div>
            <div><br>
            </div>
            <div>  function TSlice<T>.GetEnumerator:
              TSlice<T>;</div>
            <div>  begin</div>
            <div>    Result := Self;</div>
            <div>    with Result do FCurrent := FFirst - 1;</div>
            <div>  end;</div>
            <div><br>
            </div>
            <div>  function TSlice<T>.MoveNext: Boolean;</div>
            <div>  begin</div>
            <div>    Inc(FCurrent);</div>
            <div>    Exit((FCurrent <= FLast) and (FFirst <>
              FLast));</div>
            <div>  end;</div>
            <div><br>
            </div>
            <div>  function Test(const Val: SizeUInt): Boolean; inline;</div>
            <div>  begin</div>
            <div>    Exit((Val < 50000000));</div>
            <div>  end;</div>
            <div><br>
            </div>
            <div>  class function TSlice<T>.TakeWhile(const A:
              ArrayType; function F(const Val: T): Boolean):
              TSlice<T>;</div>
            <div>  var</div>
            <div>    I: SizeUInt;</div>
            <div>    X: TTestFunc<T> absolute F;</div>
            <div>    //FPC generates slightly better code for the
              "absolute" way, not sure why...</div>
            <div>  begin</div>
            <div>    with Result do begin</div>
            <div>      FFirst := @A[0];</div>
            <div>      FLast := @A[0];</div>
            <div>      for I := 0 to High(A) do</div>
            <div>        case X(A[I]) of</div>
            <div>          True: Inc(FLast);</div>
            <div>          False: Exit();</div>
            <div>        end;</div>
            <div>    end;</div>
            <div>  end;</div>
            <div><br>
            </div>
            <div>var</div>
            <div>  I, J: SizeUInt;</div>
            <div>  Arr: TSlice<SizeUInt>.ArrayType;</div>
            <div><br>
            </div>
            <div>begin</div>
            <div>  SetLength(Arr, 100000000);</div>
            <div>  for I := 0 to 99999999 do Arr[I] := I;</div>
            <div>  I := 0;</div>
            <div>  J := 0;</div>
            <div>  for I in TSlice<SizeUInt>.TakeWhile(Arr, Test)
              do J := I;</div>
            <div>  WriteLn(J);</div>
            <div>end. </div>
          </div>
        </div>
      </div>
      <br>
      <fieldset class="mimeAttachmentHeader"></fieldset>
      <pre class="moz-quote-pre" wrap="">_______________________________________________
fpc-devel maillist  -  <a class="moz-txt-link-abbreviated" href="mailto:fpc-devel@lists.freepascal.org">fpc-devel@lists.freepascal.org</a>
<a class="moz-txt-link-freetext" href="http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel">http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel</a>
</pre>
    </blockquote>
  </body>
</html>