<p style="padding:0 0 0 0; margin:0 0 0 0;">Hi,</p>

<p style="padding:0 0 0 0; margin:0 0 0 0;"> </p>

<p style="padding:0 0 0 0; margin:0 0 0 0;">I specialized my generic abstract class in a different unit with this type:</p>

<p style="padding:0 0 0 0; margin:0 0 0 0;"> </p>

<p style="padding:0 0 0 0; margin:0 0 0 0;">TRec = record</p>

<p style="padding:0 0 0 0; margin:0 0 0 0;">    A: Integer;</p>

<p style="padding:0 0 0 0; margin:0 0 0 0;">    B: Integer;</p>

<p style="padding:0 0 0 0; margin:0 0 0 0;">  end;</p>

<p style="padding:0 0 0 0; margin:0 0 0 0;"> </p>

<p style="padding:0 0 0 0; margin:0 0 0 0;">(A is for sorting, B is for testing of stability, i.e. for MergeSort, TimSort)</p>

<p style="padding:0 0 0 0; margin:0 0 0 0;"> </p>

<p style="padding:0 0 0 0; margin:0 0 0 0;">and compare function, declared with inline; directive:</p>

<p style="padding:0 0 0 0; margin:0 0 0 0;"> </p>

<p style="padding:0 0 0 0; margin:0 0 0 0;">function MyComptFunc(const ARec, BRec: TRec): Integer;</p>

<p style="padding:0 0 0 0; margin:0 0 0 0;">var i, aCnt: Integer;</p>

<p style="padding:0 0 0 0; margin:0 0 0 0;">begin</p>

<p style="padding:0 0 0 0; margin:0 0 0 0;">  aCnt:=CFComplex;</p>

<p style="padding:0 0 0 0; margin:0 0 0 0;">  for i:=0 to aCnt do</p>

<p style="padding:0 0 0 0; margin:0 0 0 0;">    Result:=(BRec.A-ARec.A);</p>

<p style="padding:0 0 0 0; margin:0 0 0 0;">  inc(CFCnt);</p>

<p style="padding:0 0 0 0; margin:0 0 0 0;">  //InterlockedIncrement(CFCnt);</p>

<p style="padding:0 0 0 0; margin:0 0 0 0;">end;              </p>

<p style="padding:0 0 0 0; margin:0 0 0 0;"> </p>

<p style="padding:0 0 0 0; margin:0 0 0 0;">The reason for this complex compare function is that it also measure number of comparisons and it can simulate more expensive comparisons (like sorting strings).</p>

<p style="padding:0 0 0 0; margin:0 0 0 0;"> </p>

<p style="padding:0 0 0 0; margin:0 0 0 0;"><span style="font-size: 10pt;">For a while, I added this unit to the second "uses" section (implementation) of the other unit, which is impractical, but I had</span></p>

<p style="padding:0 0 0 0; margin:0 0 0 0;"><span style="font-size: 10pt;">temporary access to the compare function. I tested again with ShellSort, sorting 2'000'000 values takes:</span></p>

<p style="padding:0 0 0 0; margin:0 0 0 0;">1380ms inlined</p>

<p style="padding:0 0 0 0; margin:0 0 0 0;">1515ms not inlined, ~9% slower</p>

<p style="padding:0 0 0 0; margin:0 0 0 0;">1430ms when compare func. is a parameter ~4% slower</p>

<p style="padding:0 0 0 0; margin:0 0 0 0;"> </p>

<p style="padding:0 0 0 0; margin:0 0 0 0;"><span style="font-size: 10pt;">I pass variables by value. But you are right, when I shave the function like this:</span></p>

<p style="padding:0 0 0 0; margin:0 0 0 0;"> </p>

<p style="font-size: 13.3333px;"><span style="font-size: 10pt;">function MyComptFunc(const ARec, BRec: TRec): Integer;</span></p>

<p style="font-size: 13.3333px;"><span style="font-size: 10pt;">begin</span></p>

<p style="font-size: 13.3333px;"><span style="font-size: 10pt;">  Result:=(BRec.A-ARec.A);</span></p>

<p style="font-size: 13.3333px;"><span style="font-size: 10pt;">end;</span></p>

<p style="font-size: 13.3333px;"> </p>

<p style="font-size: 13.3333px;"><span style="font-size: 10pt;">the results are:</span></p>

<p style="font-size: 13.3333px;">750ms inlined</p>

<p style="font-size: 13.3333px;">950ms not inlined, ~21% slower</p>

<p style="font-size: 13.3333px;">835ms when compare func. is a parameter ~10% slower</p>

<p style="font-size: 13.3333px;"> </p>

<p style="font-size: 13.3333px;">so the gain of inlining is higher for sorting primitive types.</p>

<div>V.</div>
<p style="padding:0 0 0 0; margin:0 0 0 0;">______________________________________________________________<br />
> Od: "Flávio Etrusco via fpc-pascal" <fpc-pascal@lists.freepascal.org><br />
> Komu: "FPC-Pascal users discussions" <fpc-pascal@lists.freepascal.org><br />
> Datum: 18.11.2022 20:45<br />
> Předmět: Re: [fpc-pascal] How to inline CompareFunc to Sort method in generic abstract class<br />
></p>

<div dir="ltr">
<div dir="auto">
<div><br />
<br />

<div class="gmail_quote">
<div class="gmail_attr" dir="ltr">Em seg., 14 de nov. de 2022 15:26, Vojtěch Čihák via fpc-pascal <<a href="mailto:fpc-pascal@lists.freepascal.org">fpc-pascal@lists.freepascal.org</a>> escreveu:<span style="font-size: 10pt;">,</span></div>
</div>
</div>
<div dir="auto">What do you mean by "be inlined"? The 'inline' directive instructs the compiler (or is it the linker? 😬) to try copying the whole function inline, also avoiding the call (stack) setup; you can't do this for this for a general purpose method.</div>
<div dir="auto">I'm curious how you got that 6% figure, it seems rather large. Is this comparing the parameter vs virtual method approach or comparing a fully inline (no indirect call of any kind) sort function to some other option? Are you passing the variables by reference?</div>
<div>Best regards,</div>
<div>Flávio</div>
</div>
</div>
<br />
 <br />
 ----------<br />
 <br />
 _______________________________________________<br />
 fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org<br />
 <a href="https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal">https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal</a><br />