From 925ee0f27e42ebef2367f8200f2dc3e238155df1 Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Thu, 12 Feb 2026 22:25:32 +0100 Subject: [PATCH] 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. --- src/steam/engine/buffer-provider.cpp | 20 +++--- src/steam/engine/buffer-provider.hpp | 8 +-- src/steam/engine/heap-mem-buffer-store.cpp | 31 +++++---- src/steam/engine/heap-mem-buffer-store.hpp | 12 ++-- wiki/thinkPad.ichthyo.mm | 73 +++++++++++++++++++++- 5 files changed, 109 insertions(+), 35 deletions(-) diff --git a/src/steam/engine/buffer-provider.cpp b/src/steam/engine/buffer-provider.cpp index 61572249c..53c56d856 100644 --- a/src/steam/engine/buffer-provider.cpp +++ b/src/steam/engine/buffer-provider.cpp @@ -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") diff --git a/src/steam/engine/buffer-provider.hpp b/src/steam/engine/buffer-provider.hpp index a6e8c8e1b..7a2f93c85 100644 --- a/src/steam/engine/buffer-provider.hpp +++ b/src/steam/engine/buffer-provider.hpp @@ -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_; ///////////////////////////////////////////////////////////TICKET #1410 : must be turned into an internal interface diff --git a/src/steam/engine/heap-mem-buffer-store.cpp b/src/steam/engine/heap-mem-buffer-store.cpp index 28dd3c31b..b6f590185 100644 --- a/src/steam/engine/heap-mem-buffer-store.cpp +++ b/src/steam/engine/heap-mem-buffer-store.cpp @@ -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); diff --git a/src/steam/engine/heap-mem-buffer-store.hpp b/src/steam/engine/heap-mem-buffer-store.hpp index 0af39deb5..148a47a8c 100644 --- a/src/steam/engine/heap-mem-buffer-store.hpp +++ b/src/steam/engine/heap-mem-buffer-store.hpp @@ -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); }; diff --git a/wiki/thinkPad.ichthyo.mm b/wiki/thinkPad.ichthyo.mm index 302ebf1e4..c76f0719b 100644 --- a/wiki/thinkPad.ichthyo.mm +++ b/wiki/thinkPad.ichthyo.mm @@ -111662,7 +111662,8 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension) - + + @@ -111687,6 +111688,14 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension) + + + + + + + + @@ -111836,6 +111845,56 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension) + + + + + + + + + + + + + + + + + + + + +

+ ...hier liegt ein potentiell gefährlicher Hebel — wenngleich auch im Fall von Buffern vermutlich nicht besonders relevant (da Buffer groß sind) +

+ + +
+ +
+ + + + + + + + +

+ Für small-objects-Allokatoren kann dieses Problem einen drastischen 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. +

+ + +
+
+
+
+ + + + +
@@ -112563,6 +112622,18 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension)
+ + + + + + + + + + + +