Chain-Load: investigate std::function inline-storage

...which is crucial for the solution pursued at the moment;
std::function is known to apply a small-object optimisation,
yet unfortunately there are no guarantees by the C++ standard
(it is only mandated that std::function handles a bare function
 pointer without overhead)

Other people have investigated that behaviour already,
indicating that at least one additional »slot« of data
can be handled with embedded storage in all known implementations
(while libstdc++ seemingly imposes the strongest limitations)
https://stackoverflow.com/a/77202545/444796

This experiment in the unit-test shows that for my setup
(libstdc++ and GCC-8) only a lambda capturing a single pointer
is handled entirely embedded into the std::function; already
a lambda capturing a shared-ptr leads to overflow into heap
This commit is contained in:
Fischlurch 2023-11-24 04:15:15 +01:00
parent 3c713a4739
commit 98078b9bb6
2 changed files with 103 additions and 6 deletions

View file

@ -30,7 +30,9 @@
#include "lib/lazy-init.hpp"
//#include "lib/format-string.hpp"
//#include "lib/test/test-helper.hpp"
#include "lib/test/testdummy.hpp"
#include "lib/test/diagnostic-output.hpp" /////////////////////TODO TODOH
#include "lib/util.hpp"
//#include <array>
@ -40,6 +42,7 @@ namespace lib {
namespace test{
// using util::_Fmt;
using util::isSameObject;
using lib::meta::isFunMember;
// using lib::meta::_FunRet;
// using err::LUMIERA_ERROR_LIFECYCLE;
@ -73,7 +76,7 @@ namespace test{
simpleUse();
verify_trojanLambda();
verify_inlineFunctorStorage();
verify_inlineStorage();
// verify_numerics();
// verify_adaptMapping();
// verify_dynamicChange();
@ -161,8 +164,48 @@ namespace test{
/** @test verify that std::function indeed stores a simple functor inline
*/
void
verify_inlineFunctorStorage()
verify_inlineStorage()
{
Dummy::checksum() = 0;
using DummyManager = std::shared_ptr<Dummy>;
DummyManager dummy{new Dummy};
long currSum = Dummy::checksum();
CHECK (currSum > 0);
CHECK (currSum == dummy->getVal());
CHECK (1 == dummy.use_count());
{
// --- nested Scope ---
auto lambda = [dummy]{ return &dummy; };
CHECK (2 == dummy.use_count());
CHECK (currSum == Dummy::checksum());
RawAddr location = lambda();
CHECK (location == &lambda);
std::function funWrap{lambda};
CHECK (funWrap);
CHECK (not isSameObject (funWrap, lambda));
CHECK (3 == dummy.use_count());
CHECK (currSum == Dummy::checksum());
SHOW_EXPR(location)
location = funWrap();
SHOW_EXPR(location)
SHOW_EXPR(RawAddr(&funWrap))
SHOW_EXPR(RawAddr(dummy.get()))
std::function fuckWrap{[location]{ return &location; }};
CHECK (fuckWrap);
SHOW_EXPR(RawAddr(&location))
SHOW_EXPR(RawAddr(fuckWrap()))
SHOW_EXPR(RawAddr(&fuckWrap))
}
CHECK (1 == dummy.use_count());
CHECK (currSum == Dummy::checksum());
dummy.reset();
CHECK (0 == dummy.use_count());
CHECK (0 == Dummy::checksum());
}

View file

@ -97285,8 +97285,9 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
</node>
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1700786308827" ID="ID_627670298" MODIFIED="1700792001666" TEXT="der Trojanische-Funktor">
<icon BUILTIN="pencil"/>
<node COLOR="#338800" CREATED="1700786329960" ID="ID_579721558" MODIFIED="1700786340287" TEXT="bettet einen shared_ptr ein">
<icon BUILTIN="button_ok"/>
<node COLOR="#5b280f" CREATED="1700786329960" ID="ID_579721558" MODIFIED="1700795318817" TEXT="bettet einen shared_ptr ein">
<linktarget COLOR="#e64156" DESTINATION="ID_579721558" ENDARROW="Default" ENDINCLINATION="556;-38;" ID="Arrow_ID_1803799256" SOURCE="ID_1318522029" STARTARROW="None" STARTINCLINATION="-60;-142;"/>
<icon BUILTIN="button_cancel"/>
</node>
<node COLOR="#338800" CREATED="1700786341382" ID="ID_1622424867" MODIFIED="1700792030724" TEXT="delegiert &#xfc;ber diesen um Funktor(Referenz) zu bekommen">
<icon BUILTIN="button_ok"/>
@ -97297,12 +97298,65 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1700786402490" ID="ID_846455233" MODIFIED="1700786418812" TEXT="Trick-Mechanismus zur this-Ermittlung">
<icon BUILTIN="flag-yellow"/>
<node CREATED="1700786427859" ID="ID_569731992" MODIFIED="1700786445020" TEXT="mu&#xdf; zu Beginn &#xbb;proben&#xab;"/>
<node CREATED="1700786446976" ID="ID_646471757" MODIFIED="1700786472569" TEXT="Zusatz-Problem: das &#x3bb; sieht nur seine capture">
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1700786427859" ID="ID_569731992" MODIFIED="1700795340778" TEXT="mu&#xdf; zu Beginn &#xbb;proben&#xab;">
<icon BUILTIN="flag-yellow"/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1700786446976" ID="ID_646471757" MODIFIED="1700795338010" TEXT="Zusatz-Problem: das &#x3bb; sieht nur seine capture">
<icon BUILTIN="flag-yellow"/>
<node CREATED="1700786476589" ID="ID_1376774629" MODIFIED="1700786490117" TEXT="&#x27f6; also mehrstufig vorgehen"/>
<node CREATED="1700786494226" ID="ID_990128277" MODIFIED="1700786508492" TEXT="generisch das Verh&#xe4;ltnis zur std::function ermitteln"/>
<node CREATED="1700786514967" ID="ID_1504854205" MODIFIED="1700786531452" TEXT="ebenso das Verh&#xe4;ltnis von der std::function zu *this"/>
</node>
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1700794680114" ID="ID_1167943729" MODIFIED="1700795330803" TEXT="Vorraussetzung: Inline-Storage in std::function">
<icon BUILTIN="pencil"/>
<node COLOR="#338800" CREATED="1700794692834" ID="ID_1004006687" MODIFIED="1700794700255" TEXT="Experiment (im Unit-Test)">
<icon BUILTIN="button_ok"/>
</node>
<node COLOR="#338800" CREATED="1700794763222" ID="ID_122093052" MODIFIED="1700794788339" TEXT="best&#xe4;tigt: &#x3bb;-Addresse == Addresse des capture im Lambda">
<icon BUILTIN="button_ok"/>
</node>
<node BACKGROUND_COLOR="#e9ecac" COLOR="#ad0163" CREATED="1700794701860" ID="ID_1782883387" MODIFIED="1700794912605">
<richcontent TYPE="NODE"><html>
<head>
</head>
<body>
<p>
<u>Ergebnis</u>: funktioniert <b>nur</b>&#160;mit 1 &#187;Slot&#171;
</p>
</body>
</html>
</richcontent>
<icon BUILTIN="broken-line"/>
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1700794792578" ID="ID_1451884191" MODIFIED="1700794849741" TEXT="wenn Lambda einfachen ptr captured &#x27fc; Stack-Addresse"/>
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1700794830533" ID="ID_871196012" MODIFIED="1700794849742" TEXT="wenn Lambda shared_ptr captured &#x27fc; Heap-Addresse"/>
</node>
<node BACKGROUND_COLOR="#fdfdcf" COLOR="#ff0000" CREATED="1700794933479" ID="ID_1065100472" MODIFIED="1700794949477" TEXT="&#x27f9; Redesign">
<icon BUILTIN="flag-pink"/>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1700795056795" ID="ID_957544868" MODIFIED="1700795103642" TEXT="der Trojaner kann lediglich das Delegate aufrufen">
<icon BUILTIN="flag-yellow"/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1700794955820" ID="ID_1318522029" MODIFIED="1700795323054" TEXT="Storage-Management mu&#xdf; separat erfolgen">
<arrowlink COLOR="#e64156" DESTINATION="ID_579721558" ENDARROW="Default" ENDINCLINATION="556;-38;" ID="Arrow_ID_1803799256" STARTARROW="None" STARTINCLINATION="-60;-142;"/>
<icon BUILTIN="flag-yellow"/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1700795105608" ID="ID_1474010761" MODIFIED="1700795128644" TEXT="bleibt nur der LazyInit-Mix-in selber">
<icon BUILTIN="idea"/>
<node BACKGROUND_COLOR="#f8f1cb" COLOR="#a50125" CREATED="1700795177255" ID="ID_1289910748" MODIFIED="1700795185358" TEXT="an beliebige Kopierbarkeit denken">
<icon BUILTIN="messagebox_warning"/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1700795186661" ID="ID_1743434660" MODIFIED="1700795272779" TEXT="der schleppt dann wohl leider einen shared_ptr mit rum">
<icon BUILTIN="flag-yellow"/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1700795238903" ID="ID_762094742" MODIFIED="1700795272779" TEXT="man k&#xf6;nnte h&#xf6;chstens nach Init abkoppeln">
<icon BUILTIN="flag-yellow"/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1700795252717" ID="ID_323775761" MODIFIED="1700795272780" TEXT="und den shared_ptr auch als Init-Flag mi&#xdf;brauchen">
<icon BUILTIN="flag-yellow"/>
</node>
</node>
</node>
</node>
</node>
</node>
</node>