BufferProvider: expand BuffStore API to provide buffer size info
This is an important step to prepare a split of the existing implementation APIs into a type-management part and a memory-allocation part; generally speaking, a memory allocator needs to know the allocation size, preferably also for releasing memory. Up to now, this information could be retrieved locally, with a metadata lookup through the hash-ID; now we ensure that the size is always passed alongside through the implementation API. Incidentally, it looks like we might be able to form a common allocation-descriptor, to represent this internal API in a more concise way. Note further that all these changes are considered not relevant for the performance, since work buffers are large and media computation dominates.
This commit is contained in:
parent
cd415c05aa
commit
925ee0f27e
5 changed files with 109 additions and 35 deletions
|
|
@ -107,9 +107,10 @@ namespace engine {
|
|||
* @note the returned count may differ from the requested count.
|
||||
*/
|
||||
uint
|
||||
BufferProvider::announce (uint count, BuffDescr const& type)
|
||||
BufferProvider::announce (uint cnt, BuffDescr const& type)
|
||||
{
|
||||
uint actually_possible = bufferStore_->prepareBuffers (count, type);
|
||||
size_t buffSiz = getBufferSize (type);
|
||||
uint actually_possible = bufferStore_->prepareBuffers (cnt, buffSiz, type);
|
||||
if (!actually_possible)
|
||||
throw error::State ("unable to fulfil request for buffers"
|
||||
,LUMIERA_ERROR_BUFFER_MANAGEMENT);
|
||||
|
|
@ -134,8 +135,8 @@ namespace engine {
|
|||
BufferProvider::lockBuffer (BuffDescr const& type)
|
||||
{
|
||||
REQUIRE (was_created_by_this_provider (type));
|
||||
|
||||
return bufferStore_->provideLockedBuffer (type);
|
||||
size_t buffSiz = getBufferSize (type);
|
||||
return bufferStore_->provideBuffer (buffSiz, type);
|
||||
} // is expected to call buildHandle() --> state transition
|
||||
|
||||
|
||||
|
|
@ -155,13 +156,14 @@ namespace engine {
|
|||
BufferProvider::emitBuffer (BuffHandle const& handle)
|
||||
{
|
||||
metadata::Entry& metaEntry = bufferStage_->get (handle.entryID());
|
||||
bufferStore_->mark_emitted (metaEntry.parentKey(), metaEntry.localTag());
|
||||
size_t buffSiz = metaEntry.storageSize();
|
||||
bufferStore_->mark_emitted (buffSiz, metaEntry.parentKey(), metaEntry.localTag());
|
||||
metaEntry.mark(EMITTED);
|
||||
}
|
||||
|
||||
|
||||
/** BufferProvider API: declare done and detach.
|
||||
* Client code is required to release \em each previously locked buffer eventually.
|
||||
* Client code is required to release _each previously locked buffer_ eventually.
|
||||
* @warning invalidates the BuffHandle, clients mustn't access the buffer anymore.
|
||||
* Right after releasing, an access through the handle will throw;
|
||||
* yet the buffer might be re-used and the handle become valid
|
||||
|
|
@ -172,8 +174,9 @@ namespace engine {
|
|||
BufferProvider::releaseBuffer (BuffHandle const& handle)
|
||||
try {
|
||||
metadata::Entry& metaEntry = bufferStage_->get (handle.entryID());
|
||||
size_t buffSiz = metaEntry.storageSize();
|
||||
metaEntry.mark(FREE); // might invoke embedded dtor function
|
||||
bufferStore_->detachBuffer (metaEntry.parentKey(), metaEntry.localTag(), *handle);
|
||||
bufferStore_->detachBuffer (buffSiz, metaEntry.parentKey(), metaEntry.localTag(), *handle);
|
||||
bufferStage_->release (metaEntry);
|
||||
}
|
||||
ERROR_LOG_AND_IGNORE (engine, "releasing a buffer from BufferProvider")
|
||||
|
|
@ -216,8 +219,9 @@ namespace engine {
|
|||
BufferProvider::emergencyCleanup (BuffHandle const& target, bool invokeDtor)
|
||||
try {
|
||||
metadata::Entry& metaEntry = bufferStage_->get (target.entryID());
|
||||
size_t buffSiz = metaEntry.storageSize();
|
||||
metaEntry.invalidate (invokeDtor);
|
||||
bufferStore_->detachBuffer (metaEntry.parentKey(), metaEntry.localTag(), *target);
|
||||
bufferStore_->detachBuffer (buffSiz, metaEntry.parentKey(), metaEntry.localTag(), *target);
|
||||
bufferStage_->release (metaEntry);
|
||||
}
|
||||
ERROR_LOG_AND_IGNORE (engine, "cleanup of buffer metadata while handling an error")
|
||||
|
|
|
|||
|
|
@ -203,10 +203,10 @@ namespace engine {
|
|||
public:
|
||||
virtual ~BufferStore() { } ///< this is an interface
|
||||
|
||||
virtual uint prepareBuffers (uint count, HashVal typeID) =0;
|
||||
virtual BuffHandle provideLockedBuffer (HashVal typeID) =0;
|
||||
virtual void mark_emitted (HashVal, LocalTag const&) =0;
|
||||
virtual void detachBuffer (HashVal, LocalTag const&, Buff&) =0;
|
||||
virtual uint prepareBuffers (uint cnt, size_t,HashVal typeID) =0;
|
||||
virtual BuffHandle provideBuffer (size_t,HashVal typeID) =0;
|
||||
virtual void mark_emitted (size_t,HashVal, LocalTag const&) =0;
|
||||
virtual void detachBuffer (size_t,HashVal, LocalTag const&, Buff&) =0;
|
||||
};
|
||||
|
||||
unique_ptr<BufferStage> bufferStage_; ///////////////////////////////////////////////////////////TICKET #1410 : must be turned into an internal interface
|
||||
|
|
|
|||
|
|
@ -281,17 +281,17 @@ namespace engine {
|
|||
/* ==== Implementation of the BufferProvider interface ==== */
|
||||
|
||||
uint
|
||||
HeapMemProvider::prepareBuffers(uint requestedAmount, HashVal typeID)
|
||||
HeapMemProvider::prepareBuffers (uint numBuffers, size_t buffSiz, HashVal typeID)
|
||||
{
|
||||
BlockPool& responsiblePool = getBlockPoolFor (typeID);
|
||||
return responsiblePool.prepare_for (requestedAmount);
|
||||
BlockPool& responsiblePool = getBlockPoolFor (buffSiz, typeID);
|
||||
return responsiblePool.prepare_for (numBuffers);
|
||||
}
|
||||
|
||||
|
||||
BuffHandle
|
||||
HeapMemProvider::provideLockedBuffer(HashVal typeID)
|
||||
HeapMemProvider::provideBuffer (size_t buffSiz, HashVal typeID)
|
||||
{
|
||||
BlockPool& blocks = getBlockPoolFor (typeID);
|
||||
BlockPool& blocks = getBlockPoolFor (buffSiz, typeID);
|
||||
Block& newBlock = blocks.createBlock();
|
||||
UNIMPLEMENTED ("Separate tasks into two distinct APIs");
|
||||
// return buildHandle (typeID, asBuffer(newBlock.accessMemory()), &newBlock); /////////////////////////////OOO instead return a tuple (buffer, localTag)
|
||||
|
|
@ -299,13 +299,13 @@ namespace engine {
|
|||
|
||||
|
||||
void
|
||||
HeapMemProvider::mark_emitted (HashVal typeID, LocalTag const& specifics)
|
||||
HeapMemProvider::mark_emitted (size_t buffSiz, HashVal typeID, LocalTag const& specifics)
|
||||
{
|
||||
Block* block4buffer = locateBlock (typeID, specifics);
|
||||
Block* block4buffer = locateBlock (buffSiz, typeID, specifics);
|
||||
if (!block4buffer)
|
||||
throw error::Logic ("Attempt to emit a buffer not known to this BufferProvider"
|
||||
, LUMIERA_ERROR_BUFFER_MANAGEMENT);
|
||||
BlockPool& pool = getBlockPoolFor (typeID);
|
||||
BlockPool& pool = getBlockPoolFor (buffSiz, typeID);
|
||||
Block* active = pool.transferResponsibility (block4buffer);
|
||||
if (active)
|
||||
outSeq_.manage (active);
|
||||
|
|
@ -320,9 +320,9 @@ namespace engine {
|
|||
|
||||
/** mark a buffer as officially discarded */
|
||||
void
|
||||
HeapMemProvider::detachBuffer (HashVal typeID, LocalTag const& specifics, Buff& storage)
|
||||
HeapMemProvider::detachBuffer (size_t buffSiz, HashVal typeID, LocalTag const& specifics, Buff& storage)
|
||||
{
|
||||
Block* block4buffer = locateBlock (typeID, specifics);
|
||||
Block* block4buffer = locateBlock (buffSiz, typeID, specifics);
|
||||
REQUIRE (block4buffer, "releasing a buffer not allocated through this provider");
|
||||
REQUIRE (util::isSameAdr (storage, block4buffer->accessMemory()));
|
||||
block4buffer->markReleased();
|
||||
|
|
@ -364,19 +364,18 @@ namespace engine {
|
|||
}
|
||||
|
||||
HeapMemProvider::BlockPool&
|
||||
HeapMemProvider::getBlockPoolFor (HashVal typeID)
|
||||
HeapMemProvider::getBlockPoolFor (size_t buffSiz, HashVal typeID)
|
||||
{
|
||||
BlockPool& pool = (*pool_)[typeID];
|
||||
UNIMPLEMENTED ("Separate tasks into two distinct APIs");
|
||||
// if (!pool)
|
||||
// pool.initialise(getBufferSize(typeID)); //////////////////////////OOO getBufferSize is a helper function in the BufferProvider protected API. Need to be "here"
|
||||
if (not pool)
|
||||
pool.initialise (buffSiz);
|
||||
return pool;
|
||||
}
|
||||
|
||||
HeapMemProvider::Block*
|
||||
HeapMemProvider::locateBlock (HashVal typeID, void* storage)
|
||||
HeapMemProvider::locateBlock (size_t buffSiz, HashVal typeID, void* storage)
|
||||
{
|
||||
BlockPool& pool = getBlockPoolFor (typeID);
|
||||
BlockPool& pool = getBlockPoolFor (buffSiz, typeID);
|
||||
Block* block4buffer = pool.find (storage); ////////////////////////////////TICKET #856
|
||||
return block4buffer? block4buffer
|
||||
: searchInOutSeqeuence (storage);
|
||||
|
|
|
|||
|
|
@ -83,10 +83,10 @@ namespace engine {
|
|||
public:
|
||||
/* === BufferStore interface === */
|
||||
|
||||
virtual uint prepareBuffers (uint count, HashVal typeID) override;
|
||||
virtual BuffHandle provideLockedBuffer (HashVal typeID) override;
|
||||
virtual void mark_emitted (HashVal, LocalTag const&) override;
|
||||
virtual void detachBuffer (HashVal, LocalTag const&, Buff&) override;
|
||||
virtual uint prepareBuffers (uint cnt, size_t,HashVal typeID) override;
|
||||
virtual BuffHandle provideBuffer (size_t,HashVal typeID) override;
|
||||
virtual void mark_emitted (size_t,HashVal, LocalTag const&) override;
|
||||
virtual void detachBuffer (size_t,HashVal, LocalTag const&, Buff&) override;
|
||||
|
||||
public:
|
||||
~HeapMemProvider();
|
||||
|
|
@ -103,8 +103,8 @@ namespace engine {
|
|||
|
||||
private:
|
||||
bool withinOutputSequence (uint bufferID) const;
|
||||
BlockPool& getBlockPoolFor (HashVal typeID);
|
||||
Block* locateBlock (HashVal typeID, void*);
|
||||
BlockPool& getBlockPoolFor (size_t,HashVal typeID);
|
||||
Block* locateBlock (size_t,HashVal typeID, void*);
|
||||
Block* searchInOutSeqeuence (void* storage);
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -111662,7 +111662,8 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension)
|
|||
<icon BUILTIN="broken-line"/>
|
||||
</node>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#f8f1cb" COLOR="#a50125" CREATED="1770771226721" ID="ID_1487577652" MODIFIED="1770771248247" TEXT="auch der DiagnosticBufferProvider verwendet ein Basis_API: getBufferSize()">
|
||||
<node BACKGROUND_COLOR="#f8f1cb" COLOR="#a50125" CREATED="1770771226721" ID="ID_1487577652" MODIFIED="1770929553915" TEXT="die Provider-Implementierungen verwendet ein Basis_API: getBufferSize()">
|
||||
<linktarget COLOR="#fd583f" DESTINATION="ID_1487577652" ENDARROW="Default" ENDINCLINATION="-484;20;" ID="Arrow_ID_1256483946" SOURCE="ID_831737885" STARTARROW="None" STARTINCLINATION="-70;-57;"/>
|
||||
<icon BUILTIN="messagebox_warning"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1770770126934" ID="ID_850948251" MODIFIED="1770770161242" TEXT="⟹ API-Anpassung notwendig">
|
||||
|
|
@ -111687,6 +111688,14 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension)
|
|||
<node BACKGROUND_COLOR="#fdfdcf" COLOR="#ff0000" CREATED="1770770350662" ID="ID_1511113078" MODIFIED="1770835721461" TEXT="Lösung ist offensichtlich: auseinander-fädeln">
|
||||
<linktarget COLOR="#fe3e3a" DESTINATION="ID_1511113078" ENDARROW="Default" ENDINCLINATION="243;15;" ID="Arrow_ID_1668459979" SOURCE="ID_661880079" STARTARROW="None" STARTINCLINATION="636;0;"/>
|
||||
<icon BUILTIN="yes"/>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1770929471826" ID="ID_472477187" MODIFIED="1770934001172" TEXT="Buffer-Store rein auf die Allokationen fokussieren">
|
||||
<arrowlink COLOR="#616d7c" DESTINATION="ID_1572913456" ENDARROW="Default" ENDINCLINATION="433;33;" ID="Arrow_ID_1937407092" STARTARROW="None" STARTINCLINATION="1162;357;"/>
|
||||
<linktarget COLOR="#692bc7" DESTINATION="ID_472477187" ENDARROW="Default" ENDINCLINATION="304;203;" ID="Arrow_ID_396413173" SOURCE="ID_756237025" STARTARROW="None" STARTINCLINATION="347;19;"/>
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
<node CREATED="1770932643675" ID="ID_1799354299" MODIFIED="1770932643675" TEXT="provideBuffer (size_t,HashVal typeID)"/>
|
||||
<node CREATED="1770933709677" MODIFIED="1770933709677" TEXT="prepareBuffers (uint cnt, size_t,HashVal typeID)"/>
|
||||
<node CREATED="1770933720241" MODIFIED="1770933720241" TEXT="detachBuffer (size_t,HashVal, LocalTag const&, Buff&)"/>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
|
|
@ -111836,6 +111845,56 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension)
|
|||
<arrowlink COLOR="#fe3e3a" DESTINATION="ID_1511113078" ENDARROW="Default" ENDINCLINATION="243;15;" ID="Arrow_ID_1668459979" STARTARROW="None" STARTINCLINATION="636;0;"/>
|
||||
<icon BUILTIN="flag-pink"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#fdfdcf" COLOR="#ff0000" CREATED="1770926260075" ID="ID_831737885" MODIFIED="1770929560653" TEXT="interner Zugriff auf buffer-size">
|
||||
<arrowlink COLOR="#fd583f" DESTINATION="ID_1487577652" ENDARROW="Default" ENDINCLINATION="-484;20;" ID="Arrow_ID_1256483946" STARTARROW="None" STARTINCLINATION="-70;-57;"/>
|
||||
<icon BUILTIN="flag-pink"/>
|
||||
<node BACKGROUND_COLOR="#f0d5c5" COLOR="#990033" CREATED="1770926385056" ID="ID_1327594403" MODIFIED="1770926436770" TEXT="verwendet von getBlockPoolFor(HashVal) ⟵ in sehr vielen Aufrufen der erste Schritt">
|
||||
<icon BUILTIN="clanbomber"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#f8f1cb" COLOR="#a50125" CREATED="1770926280226" ID="ID_1629789719" MODIFIED="1770926305170" TEXT="bisher über Hilfsfunktion auf der BufferProvider Basis-impl">
|
||||
<icon BUILTIN="messagebox_warning"/>
|
||||
<node CREATED="1770926311965" ID="ID_1256083121" MODIFIED="1770926337047" TEXT="dies verletzt jetzt die Verschachtelung"/>
|
||||
<node CREATED="1770926338187" ID="ID_788003404" MODIFIED="1770926343457" TEXT="und die Trennung der Themen"/>
|
||||
<node CREATED="1770926346025" ID="ID_817787716" MODIFIED="1770926361362" TEXT="ist nämlich implementiert durch Zugriff auf die Type-Registry"/>
|
||||
</node>
|
||||
<node CREATED="1770929023368" ID="ID_448168342" MODIFIED="1770929048141" TEXT="Einschätzung: muß ohnehin geändert werden">
|
||||
<icon BUILTIN="yes"/>
|
||||
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1770929095659" ID="ID_374106644" MODIFIED="1770929259555" TEXT="wir vermerken die Size nur einmal: im Typ-descriptor">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<p>
|
||||
...hier liegt ein potentiell gefährlicher Hebel — wenngleich auch im Fall von Buffern vermutlich nicht besonders relevant (da Buffer groß sind)
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
<icon BUILTIN="messagebox_warning"/>
|
||||
</node>
|
||||
<node CREATED="1770929050952" ID="ID_1844454362" MODIFIED="1770929066192" TEXT="ein typischer Allokator muß die Größe wissen">
|
||||
<node CREATED="1770929067315" ID="ID_1319809000" MODIFIED="1770929074957" TEXT="vor allem auch zur de-Allokation"/>
|
||||
<node CREATED="1770929216403" ID="ID_1022871277" MODIFIED="1770929358425" TEXT="ein bekanntes Problem mit vielen Workarounds und Kniffen">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<p>
|
||||
Für small-objects-Allokatoren kann dieses Problem einen <i>drastischen</i> Einfluß auf die Performance haben. Im konkreten Fall ist die Situation so komplex, daß ich tunlichst jedwede Art von Abschätzung und Optimierung vermeiden sollte.
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
<node CREATED="1770929365917" ID="ID_756237025" MODIFIED="1770929600076" TEXT="Konsequenz ⟹ API in dieser Hinsicht sofort anpassen">
|
||||
<arrowlink COLOR="#692bc7" DESTINATION="ID_472477187" ENDARROW="Default" ENDINCLINATION="304;203;" ID="Arrow_ID_396413173" STARTARROW="None" STARTINCLINATION="347;19;"/>
|
||||
</node>
|
||||
<node CREATED="1770934037162" ID="ID_1977306902" MODIFIED="1770934049026" TEXT="getBlockPoolFor(size,HashVal)"/>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1770762458610" ID="ID_875010759" MODIFIED="1770762816021" TEXT="DiagnosticBufferProvider anpassen">
|
||||
|
|
@ -112563,6 +112622,18 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension)
|
|||
</node>
|
||||
</node>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1770933762544" ID="ID_389070880" MODIFIED="1770933775068" TEXT="Tendenzen zeichnen sich ab...">
|
||||
<icon BUILTIN="idea"/>
|
||||
<node CREATED="1770933776885" ID="ID_1667378564" MODIFIED="1770933789787" TEXT="für das Store-Interface">
|
||||
<node CREATED="1770933791395" ID="ID_1572913456" MODIFIED="1770934001172" TEXT="...wird überall die buffSize mitgegeben">
|
||||
<linktarget COLOR="#616d7c" DESTINATION="ID_1572913456" ENDARROW="Default" ENDINCLINATION="433;33;" ID="Arrow_ID_1937407092" SOURCE="ID_472477187" STARTARROW="None" STARTINCLINATION="1162;357;"/>
|
||||
</node>
|
||||
<node CREATED="1770933799954" ID="ID_1059437311" MODIFIED="1770933811425" TEXT="denkbar auch, das LocalTag überall durchzufädeln"/>
|
||||
<node CREATED="1770933813057" ID="ID_1110032982" MODIFIED="1770933835165" TEXT="man könnte das in eine BuffInfo packen">
|
||||
<icon BUILTIN="idea"/>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
|
|
|
|||
Loading…
Reference in a new issue