<div dir="auto"><div>Hi,</div><div dir="auto"><br></div><div dir="auto">Thanks for the clarifications (although in some aspects I'm more confused now LOL).</div><div dir="auto"><br></div><div dir="auto">If you really want the performance gains (and if you're convinced of these gains, of course) maybe you could implement inlined functions for each key native datatype taking an offset for the field.</div><div dir="auto"><br></div><div dir="auto">And if you have computed or complex keys, creating an indirection list would probably have speed gains.</div><div dir="auto"><br></div><div dir="auto">--</div><div dir="auto">Best regards, </div><div dir="auto">Flavio<br><br><div class="gmail_quote" dir="auto"><div dir="ltr" class="gmail_attr">Em sáb., 19 de nov. de 2022 00:26, Vojtěch Čihák via fpc-pascal <<a href="mailto:fpc-pascal@lists.freepascal.org" target="_blank" rel="noreferrer">fpc-pascal@lists.freepascal.org</a>> escreveu:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><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" <<a href="mailto:fpc-pascal@lists.freepascal.org" rel="noreferrer noreferrer" target="_blank">fpc-pascal@lists.freepascal.org</a>><br>
> Komu: "FPC-Pascal users discussions" <<a href="mailto:fpc-pascal@lists.freepascal.org" rel="noreferrer noreferrer" target="_blank">fpc-pascal@lists.freepascal.org</a>><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" rel="noreferrer noreferrer" target="_blank">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 - <a href="mailto:fpc-pascal@lists.freepascal.org" rel="noreferrer noreferrer" target="_blank">fpc-pascal@lists.freepascal.org</a><br>
<a href="https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal" rel="noreferrer noreferrer" target="_blank">https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal</a><br>
_______________________________________________<br>
fpc-pascal maillist - <a href="mailto:fpc-pascal@lists.freepascal.org" rel="noreferrer noreferrer" target="_blank">fpc-pascal@lists.freepascal.org</a><br>
<a href="https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal" rel="noreferrer noreferrer noreferrer" target="_blank">https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal</a><br>
</blockquote></div></div></div>