BufferProvider: integrate and verify heuristic trigger of clean-up
The mechanism is tuned now to engage rather quickly whenever excess capacity builds up in a local allocator pool, but when all buffers are used most of the time, they will be retained. Can now demonstrate by integration test that capacity is sent back.
This commit is contained in:
parent
5a7cfb613f
commit
7989e825b9
5 changed files with 236 additions and 209 deletions
|
|
@ -51,6 +51,12 @@
|
|||
namespace vault {
|
||||
namespace mem {
|
||||
|
||||
namespace { // tuning parameters for clean-up heuristics
|
||||
|
||||
const double TRIGGER_SENSITIVIY = 1.0; ///< sensitivity of re-triggering based on max-score and turnover
|
||||
const double HEURISTIC_CLEANUP = 0.5; ///< cut-off percentage of max-score; blocks with lower score will be sent back
|
||||
}
|
||||
|
||||
using util::_Fmt;
|
||||
|
||||
class LocalStoreDiagnostic;
|
||||
|
|
@ -73,16 +79,28 @@ namespace mem {
|
|||
* This implementation of the BufferProvider::BufferStore interface
|
||||
* deliberately skips further sanity checks, beyond what is enforced
|
||||
* through the BufferMetadata lifecycle. Allocation requests are
|
||||
* passed to the LocalMemPool for the current thread.
|
||||
* delegated to the LocalMemPool for the current thread.
|
||||
*
|
||||
* The PoolSetup creates a connection to the EngineBufferManager,
|
||||
* retrieved via lib::Depend, so each thread-local pool can unwind
|
||||
* automatically at thread end and return all leased storage.
|
||||
*/
|
||||
class LocalBufferStore
|
||||
: public BufferProviderSetup::Store
|
||||
{
|
||||
struct SetupPool;
|
||||
using LocalPool = lib::LocalSlice<LocalMemPool, SetupPool>;
|
||||
struct PoolSetup;
|
||||
using LocalPool = lib::LocalSlice<LocalMemPool, PoolSetup>;
|
||||
using GlobalPool = lib::Depend<EngineBufferManager>;
|
||||
|
||||
struct SetupPool
|
||||
static void
|
||||
send_back2globalPool (Buff* mem, size_t siz)
|
||||
{
|
||||
Alloc alloc{mem,siz};
|
||||
GlobalPool globalPool;
|
||||
globalPool().supply(alloc);
|
||||
}
|
||||
|
||||
struct PoolSetup
|
||||
{
|
||||
using Service = LocalMemPool;
|
||||
|
||||
|
|
@ -91,12 +109,7 @@ namespace mem {
|
|||
{
|
||||
return LocalMemPool{[](LocalMemPool& pool2close)
|
||||
{
|
||||
pool2close.purge([](Buff* mem, size_t siz)
|
||||
{
|
||||
Alloc alloc{mem,siz};
|
||||
GlobalPool globalPool;
|
||||
globalPool().supply(alloc);
|
||||
});
|
||||
pool2close.purge (send_back2globalPool);
|
||||
}};
|
||||
}
|
||||
};
|
||||
|
|
@ -105,8 +118,7 @@ namespace mem {
|
|||
GlobalPool globalPool_;
|
||||
|
||||
public:
|
||||
LocalBufferStore()
|
||||
{ }
|
||||
LocalBufferStore() { }
|
||||
|
||||
|
||||
|
||||
|
|
@ -191,15 +203,19 @@ namespace mem {
|
|||
auto& [storage,buffSiz,specifics] = storageSlot;
|
||||
REQUIRE (storage);
|
||||
localPool_->reSupply (storage);
|
||||
/////////////////////////////////////////////////////OOO trigger heuristic clean-up here
|
||||
if (localPool_->shouldCleanup (TRIGGER_SENSITIVIY))
|
||||
localPool_->cleanup (HEURISTIC_CLEANUP
|
||||
,send_back2globalPool);
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
/** diagnostic access for unit testing */
|
||||
friend PoolDiagnostic watch (LocalBufferStore const&);
|
||||
};
|
||||
|
||||
|
||||
|
||||
/** entrance point to inspection for test */
|
||||
inline PoolDiagnostic
|
||||
watch (LocalBufferStore const& lstor)
|
||||
|
|
|
|||
|
|
@ -205,9 +205,9 @@ namespace mem {
|
|||
|
||||
/** turnover-based trigger for heuristic pool clean-up */
|
||||
bool
|
||||
shouldCleanup (float sharpen =1.0f) const
|
||||
shouldCleanup (double sharpen =1.0f) const
|
||||
{
|
||||
return turnover_ * float(MATCH_SCORE) <= maxScore_ * sharpen;
|
||||
return turnover_ * double(MATCH_SCORE) <= maxScore_ * sharpen;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -24,7 +24,6 @@
|
|||
#include "lib/depend-inject.hpp"
|
||||
#include "lib/thread.hpp"
|
||||
#include "lib/util.hpp"
|
||||
#include "test/diagnostic-output.hpp"///////////////////////TODO
|
||||
|
||||
#include <algorithm>
|
||||
#include <atomic>
|
||||
|
|
@ -40,28 +39,11 @@ namespace vault {
|
|||
namespace mem {
|
||||
namespace test {
|
||||
|
||||
// using LERR_(LOGIC);
|
||||
// using LERR_(LIFECYCLE);
|
||||
|
||||
|
||||
namespace { // Test helper
|
||||
|
||||
// template<typename X>
|
||||
// Buff*
|
||||
// mark_as_Buffer(X& something)
|
||||
// {
|
||||
// return reinterpret_cast<Buff*> (std::addressof(something));
|
||||
// }
|
||||
//
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**************************************************************************//**
|
||||
* @test verify worker memory handling that relies on a thread-local allocator.
|
||||
/*********************************************//**
|
||||
* @test verify memory handling in worker
|
||||
* that relies on a thread-local allocation pool.
|
||||
*/
|
||||
class LocalBufferStore_test : public Test
|
||||
{
|
||||
|
|
@ -69,8 +51,6 @@ namespace test {
|
|||
virtual void
|
||||
run (Arg)
|
||||
{
|
||||
// seedRand();
|
||||
|
||||
verify_API();
|
||||
verify_announce();
|
||||
verify_allocate();
|
||||
|
|
@ -372,7 +352,7 @@ namespace test {
|
|||
/** @test heuristic clean-up after releasing several allocations
|
||||
* - at first, a de-allocated block remains available in the local pool
|
||||
* - after a number of usages, defined as _turnover_, clean-up is triggered
|
||||
* - this test scenario requests 3 buffers, but repeatedly uses only one
|
||||
* - this test scenario requests 5 buffers, but repeatedly uses only one
|
||||
* - after the third round with this usage pattern, the local pool is reduced
|
||||
*/
|
||||
void
|
||||
|
|
@ -394,7 +374,7 @@ namespace test {
|
|||
Thread testWorker{[&] /* === Scenario: test subject requests allocation immediately === */
|
||||
{
|
||||
// Step-1 : first round
|
||||
uint avail = storeAPI.prepareBuffers(TYPEID, 3, BUFFSIZ);
|
||||
uint avail = storeAPI.prepareBuffers(TYPEID, 5, BUFFSIZ);
|
||||
CHECK (0 == avail);
|
||||
CHECK (watch(localStore).isEmpty());
|
||||
|
||||
|
|
@ -403,36 +383,40 @@ namespace test {
|
|||
CHECK (storage);
|
||||
|
||||
storeAPI.detachBuffer (TYPEID, slot1);
|
||||
// Result: got three allocations and all three are in the local pool
|
||||
CHECK (watch(localStore).size() == 3);
|
||||
CHECK (watch(localStore).cntFree() == 3);
|
||||
// Result: got five allocations and all are in the local pool
|
||||
CHECK (watch(localStore).size() == 5);
|
||||
CHECK (watch(localStore).cntFree() == 5);
|
||||
|
||||
++step;
|
||||
// Step-2 : repeat same pattern
|
||||
// Step-2 : repeat same pattern -- again only using one of the five buffers
|
||||
BuffAlloc slot2 = storeAPI.provideBuffer (TYPEID, BUFFSIZ, 0,0);
|
||||
CHECK (slot2 == slot1);
|
||||
CHECK (watch(localStore).size() == 3);
|
||||
CHECK (watch(localStore).cntFree() == 2);
|
||||
CHECK (watch(localStore).size() == 5);
|
||||
CHECK (watch(localStore).cntFree() == 4);
|
||||
|
||||
storeAPI.detachBuffer (TYPEID, slot1);
|
||||
CHECK (watch(localStore).size() == 3);
|
||||
CHECK (watch(localStore).cntFree() == 3);
|
||||
CHECK (watch(localStore).size() == 5);
|
||||
CHECK (watch(localStore).cntFree() == 5);
|
||||
|
||||
++step;
|
||||
// Step-3 : repeat for a third time
|
||||
BuffAlloc slot3 = storeAPI.provideBuffer (TYPEID, BUFFSIZ, 0,0);
|
||||
CHECK (slot3 == slot1);
|
||||
CHECK (watch(localStore).size() == 3);
|
||||
CHECK (watch(localStore).cntFree() == 2);
|
||||
CHECK (watch(localStore).size() == 5);
|
||||
CHECK (watch(localStore).cntFree() == 4);
|
||||
|
||||
storeAPI.detachBuffer (TYPEID, slot1);
|
||||
// this completed a "turnover" of three buffers
|
||||
SHOW_EXPR(watch(localStore).size());
|
||||
// this triggered a clean-up and detected the unused capacity
|
||||
CHECK (watch(localStore).size() == 1);
|
||||
CHECK (watch(localStore).cntFree() == 1);
|
||||
|
||||
++step;
|
||||
// main thread will now see the partial clean-up
|
||||
|
||||
}}; // block automatically sent back after thread end
|
||||
while (step == 4) // wait until main thread could investigate
|
||||
sleep_for(1ms);
|
||||
|
||||
}}; // remaining buffer automatically sent back after thread end
|
||||
|
||||
|
||||
/* === Main thread: observe effects in the global pool === */
|
||||
|
|
@ -440,19 +424,31 @@ namespace test {
|
|||
// wait until Step-2
|
||||
while (step < 2)
|
||||
sleep_for(1ms);
|
||||
CHECK (watch(*globalPool).numAllocs() == 3);
|
||||
CHECK (watch(*globalPool).numAllocs() == 5);
|
||||
|
||||
// re-check after Step-2
|
||||
while (step <= 2)
|
||||
sleep_for(1ms);
|
||||
// nothing changed; local pool operates independently
|
||||
CHECK (watch(*globalPool).numAllocs() == 3);
|
||||
CHECK (watch(*globalPool).numAllocs() == 5);
|
||||
CHECK (watch(*globalPool).bytesLeased() == 5*BUFFSIZ);
|
||||
|
||||
// re-check after Step-3
|
||||
while (step <= 3)
|
||||
sleep_for(1ms);
|
||||
globalPool->processPendingRequests();
|
||||
SHOW_EXPR(watch(*globalPool).numAllocs())
|
||||
CHECK (watch(*globalPool).bytesLeased() == 1*BUFFSIZ);
|
||||
// Note: local pool sent back excess capacity
|
||||
|
||||
++step; // allow the worker to terminate after that
|
||||
|
||||
while (testWorker)
|
||||
sleep_for(1ms);
|
||||
sleep_for(1ms); // additional wait for the dtor
|
||||
|
||||
globalPool->processPendingRequests();
|
||||
CHECK (watch(*globalPool).bytesLeased() == 0);
|
||||
// all capacity properly returned into global pool
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -306,6 +306,7 @@ namespace test {
|
|||
|
||||
|
||||
|
||||
|
||||
/** @test heuristic trigger mechanism for pool clean-up
|
||||
* - use a setup where the global pool is just a queue of buffer pointers
|
||||
* - create abbreviated notation to play through various scenarios
|
||||
|
|
@ -377,208 +378,199 @@ namespace test {
|
|||
.feed(MEM32)
|
||||
.feed(MEM33);
|
||||
|
||||
SHOW_EXPR(show(globalPool));
|
||||
SHOW_EXPR(watch(pool).size())
|
||||
SHOW_EXPR(watch(pool).getMaxScore())
|
||||
SHOW_EXPR(watch(pool).getTurnover())
|
||||
|
||||
CHECK (0 == watch(pool).size() );
|
||||
CHECK (0 == watch(pool).getTurnover() );
|
||||
|
||||
supply(3);
|
||||
|
||||
SHOW_EXPR("supply")
|
||||
SHOW_EXPR(show(globalPool));
|
||||
SHOW_EXPR(watch(pool).size())
|
||||
SHOW_EXPR(watch(pool).cntFree())
|
||||
|
||||
reserve(2);
|
||||
|
||||
SHOW_EXPR("reserve")
|
||||
SHOW_EXPR(watch(pool).size())
|
||||
SHOW_EXPR(watch(pool).cntFree())
|
||||
SHOW_EXPR(watch(pool).cntResd())
|
||||
SHOW_EXPR(watch(pool).getMaxScore())
|
||||
SHOW_EXPR(watch(pool).getTurnover())
|
||||
CHECK (3 == watch(pool).size() );
|
||||
CHECK (3 == watch(pool).cntFree() );
|
||||
CHECK (2 == watch(pool).cntResd() );
|
||||
CHECK (1 == watch(pool).getMaxScore() );
|
||||
CHECK (3 == watch(pool).getTurnover() );
|
||||
|
||||
|
||||
//------------ PATTERN-1 : use complete local capacity
|
||||
claim(3);
|
||||
|
||||
SHOW_EXPR("claim")
|
||||
SHOW_EXPR(watch(pool).size())
|
||||
SHOW_EXPR(watch(pool).cntFree())
|
||||
SHOW_EXPR(watch(pool).cntResd())
|
||||
SHOW_EXPR(watch(pool).getMaxScore())
|
||||
SHOW_EXPR(watch(pool).getTurnover())
|
||||
SHOW_EXPR(show(usedBuff));
|
||||
CHECK ( 3 == watch(pool).size() );
|
||||
CHECK ( 0 == watch(pool).cntFree() );
|
||||
CHECK ( 0 == watch(pool).cntResd() );
|
||||
CHECK (10 == watch(pool).getMaxScore() );
|
||||
CHECK ( 3 == watch(pool).getTurnover() );
|
||||
|
||||
free(3);
|
||||
|
||||
SHOW_EXPR("free")
|
||||
SHOW_EXPR(watch(pool).size())
|
||||
SHOW_EXPR(watch(pool).cntFree())
|
||||
SHOW_EXPR(watch(pool).cntResd())
|
||||
SHOW_EXPR(watch(pool).getMaxScore())
|
||||
SHOW_EXPR(watch(pool).getTurnover())
|
||||
SHOW_EXPR(show(usedBuff));
|
||||
CHECK ( 3 == watch(pool).size() );
|
||||
CHECK ( 3 == watch(pool).cntFree() );
|
||||
CHECK (10 == watch(pool).getMaxScore() );
|
||||
CHECK ( 0 == watch(pool).getTurnover() );
|
||||
|
||||
SHOW_EXPR(pool.shouldCleanup())
|
||||
// heuristic trigger fires at that point,
|
||||
// since full capacity was »turned over« once
|
||||
CHECK (pool.shouldCleanup() );
|
||||
|
||||
uint removed = pool.cleanup(0.5, pushMem);
|
||||
SHOW_EXPR(removed)
|
||||
// However, nothing was removed, since all elements
|
||||
// were used efficiently and are thus close to maxScore
|
||||
CHECK (0 == removed);
|
||||
CHECK (show(globalPool) == "21, 31, 32, 33"_expect);
|
||||
|
||||
SHOW_EXPR(watch(pool).size())
|
||||
SHOW_EXPR(watch(pool).getMaxScore())
|
||||
SHOW_EXPR(watch(pool).getTurnover())
|
||||
SHOW_EXPR(show(globalPool));
|
||||
CHECK ( 3 == watch(pool).size() );
|
||||
CHECK ( 5 == watch(pool).getMaxScore() );
|
||||
// turnover is re-set to current pool size
|
||||
CHECK ( 3 == watch(pool).getTurnover() );
|
||||
|
||||
|
||||
//------------ PATTERN-2 : use only one buffer a time (inefficient)
|
||||
claim(1);
|
||||
|
||||
SHOW_EXPR("claim")
|
||||
SHOW_EXPR(watch(pool).size())
|
||||
SHOW_EXPR(watch(pool).cntFree())
|
||||
SHOW_EXPR(watch(pool).cntResd())
|
||||
SHOW_EXPR(watch(pool).getMaxScore())
|
||||
SHOW_EXPR(watch(pool).getTurnover())
|
||||
CHECK ( 3 == watch(pool).size() );
|
||||
CHECK ( 2 == watch(pool).cntFree() );
|
||||
CHECK (15 == watch(pool).getMaxScore() );
|
||||
CHECK ( 3 == watch(pool).getTurnover() );
|
||||
|
||||
free(1);
|
||||
|
||||
SHOW_EXPR("free")
|
||||
SHOW_EXPR(watch(pool).size())
|
||||
SHOW_EXPR(watch(pool).cntFree())
|
||||
SHOW_EXPR(watch(pool).cntResd())
|
||||
SHOW_EXPR(watch(pool).getMaxScore())
|
||||
SHOW_EXPR(watch(pool).getTurnover())
|
||||
CHECK ( 3 == watch(pool).size() );
|
||||
CHECK ( 3 == watch(pool).cntFree() );
|
||||
CHECK (15 == watch(pool).getMaxScore() );
|
||||
CHECK ( 2 == watch(pool).getTurnover() );
|
||||
|
||||
SHOW_EXPR(pool.shouldCleanup())
|
||||
// not yet hitting the trigger...
|
||||
CHECK (not pool.shouldCleanup() );
|
||||
|
||||
claim(1);
|
||||
|
||||
SHOW_EXPR("claim")
|
||||
SHOW_EXPR(watch(pool).size())
|
||||
SHOW_EXPR(watch(pool).cntFree())
|
||||
SHOW_EXPR(watch(pool).cntResd())
|
||||
SHOW_EXPR(watch(pool).getMaxScore())
|
||||
SHOW_EXPR(watch(pool).getTurnover())
|
||||
CHECK ( 3 == watch(pool).size() );
|
||||
CHECK ( 2 == watch(pool).cntFree() );
|
||||
CHECK (25 == watch(pool).getMaxScore() );
|
||||
CHECK ( 2 == watch(pool).getTurnover() );
|
||||
|
||||
free(1);
|
||||
|
||||
SHOW_EXPR("free")
|
||||
SHOW_EXPR(watch(pool).size())
|
||||
SHOW_EXPR(watch(pool).cntFree())
|
||||
SHOW_EXPR(watch(pool).getMaxScore())
|
||||
SHOW_EXPR(watch(pool).getTurnover())
|
||||
CHECK ( 3 == watch(pool).size() );
|
||||
CHECK ( 3 == watch(pool).cntFree() );
|
||||
CHECK (25 == watch(pool).getMaxScore() );
|
||||
CHECK ( 1 == watch(pool).getTurnover() );
|
||||
|
||||
SHOW_EXPR(pool.shouldCleanup())
|
||||
// maxScore did increase a lot,
|
||||
// since effectively just a single buffer was used all the time
|
||||
|
||||
CHECK (pool.shouldCleanup() );
|
||||
|
||||
removed = pool.cleanup(0.5, pushMem);
|
||||
SHOW_EXPR(removed)
|
||||
// Consequently the two superfluous buffers will be sent back
|
||||
// (cutoff-score is at 12; maxScore will be lowered by that amount afterwards)
|
||||
CHECK (2 == removed );
|
||||
CHECK (show(globalPool) == "21, 31, 32, 33, 12, 11"_expect);
|
||||
|
||||
SHOW_EXPR(watch(pool).size())
|
||||
SHOW_EXPR(watch(pool).getMaxScore())
|
||||
SHOW_EXPR(watch(pool).getTurnover())
|
||||
SHOW_EXPR(show(globalPool));
|
||||
CHECK ( 1 == watch(pool).size() );
|
||||
CHECK ( 1 == watch(pool).cntFree() );
|
||||
CHECK (13 == watch(pool).getMaxScore() );
|
||||
CHECK ( 1 == watch(pool).getTurnover() );
|
||||
|
||||
|
||||
//------------ PATTERN-3 : dynamic partially overlapping usage
|
||||
supply(4);
|
||||
SHOW_EXPR("supply")
|
||||
SHOW_EXPR(watch(pool).size())
|
||||
SHOW_EXPR(watch(pool).getMaxScore())
|
||||
SHOW_EXPR(watch(pool).getTurnover())
|
||||
SHOW_EXPR(show(globalPool));
|
||||
|
||||
CHECK ( 5 == watch(pool).size() );
|
||||
CHECK ( 5 == watch(pool).cntFree() );
|
||||
CHECK (13 == watch(pool).getMaxScore() );
|
||||
CHECK ( 5 == watch(pool).getTurnover() );
|
||||
// turnover was bumped +4 due to increased supply
|
||||
|
||||
claim(3);
|
||||
|
||||
SHOW_EXPR("claim")
|
||||
SHOW_EXPR(watch(pool).size())
|
||||
SHOW_EXPR(watch(pool).cntFree())
|
||||
SHOW_EXPR(watch(pool).cntResd())
|
||||
SHOW_EXPR(watch(pool).getMaxScore())
|
||||
SHOW_EXPR(watch(pool).getTurnover())
|
||||
CHECK ( 5 == watch(pool).size() );
|
||||
CHECK ( 2 == watch(pool).cntFree() );
|
||||
CHECK (13 == watch(pool).getMaxScore() );
|
||||
CHECK ( 5 == watch(pool).getTurnover() );
|
||||
|
||||
free(2);
|
||||
|
||||
SHOW_EXPR("free")
|
||||
SHOW_EXPR(watch(pool).size())
|
||||
SHOW_EXPR(watch(pool).cntFree())
|
||||
SHOW_EXPR(watch(pool).cntResd())
|
||||
SHOW_EXPR(watch(pool).getMaxScore())
|
||||
SHOW_EXPR(watch(pool).getTurnover())
|
||||
CHECK ( 5 == watch(pool).size() );
|
||||
CHECK ( 4 == watch(pool).cntFree() );
|
||||
CHECK (13 == watch(pool).getMaxScore() );
|
||||
CHECK ( 3 == watch(pool).getTurnover() );
|
||||
|
||||
SHOW_EXPR(pool.shouldCleanup())
|
||||
CHECK (not pool.shouldCleanup() );
|
||||
// no complete turnover cycle yet
|
||||
|
||||
claim(2);
|
||||
|
||||
SHOW_EXPR("claim")
|
||||
SHOW_EXPR(watch(pool).size())
|
||||
SHOW_EXPR(watch(pool).cntFree())
|
||||
SHOW_EXPR(watch(pool).cntResd())
|
||||
SHOW_EXPR(watch(pool).getMaxScore())
|
||||
SHOW_EXPR(watch(pool).getTurnover())
|
||||
CHECK ( 5 == watch(pool).size() );
|
||||
CHECK ( 2 == watch(pool).cntFree() );
|
||||
CHECK (20 == watch(pool).getMaxScore() );
|
||||
CHECK ( 3 == watch(pool).getTurnover() );
|
||||
|
||||
supply(4);
|
||||
SHOW_EXPR("supply")
|
||||
SHOW_EXPR(watch(pool).size())
|
||||
SHOW_EXPR(watch(pool).getMaxScore())
|
||||
SHOW_EXPR(watch(pool).getTurnover())
|
||||
SHOW_EXPR(show(globalPool));
|
||||
|
||||
CHECK ( 7 == watch(pool).size() );
|
||||
CHECK ( 4 == watch(pool).cntFree() );
|
||||
CHECK (20 == watch(pool).getMaxScore() );
|
||||
CHECK ( 5 == watch(pool).getTurnover() );
|
||||
|
||||
free(2);
|
||||
|
||||
SHOW_EXPR("free")
|
||||
SHOW_EXPR(watch(pool).size())
|
||||
SHOW_EXPR(watch(pool).cntFree())
|
||||
SHOW_EXPR(watch(pool).getMaxScore())
|
||||
SHOW_EXPR(watch(pool).getTurnover())
|
||||
SHOW_EXPR(show(usedBuff));
|
||||
CHECK ( 7 == watch(pool).size() );
|
||||
CHECK ( 6 == watch(pool).cntFree() );
|
||||
CHECK (20 == watch(pool).getMaxScore() );
|
||||
CHECK ( 3 == watch(pool).getTurnover() );
|
||||
|
||||
claim(1);
|
||||
|
||||
SHOW_EXPR("claim")
|
||||
SHOW_EXPR(watch(pool).size())
|
||||
SHOW_EXPR(watch(pool).cntFree())
|
||||
SHOW_EXPR(watch(pool).cntResd())
|
||||
SHOW_EXPR(watch(pool).getMaxScore())
|
||||
SHOW_EXPR(watch(pool).getTurnover())
|
||||
CHECK ( 7 == watch(pool).size() );
|
||||
CHECK ( 5 == watch(pool).cntFree() );
|
||||
CHECK (20 == watch(pool).getMaxScore() );
|
||||
CHECK ( 3 == watch(pool).getTurnover() );
|
||||
|
||||
free(1);
|
||||
|
||||
SHOW_EXPR("free")
|
||||
SHOW_EXPR(watch(pool).size())
|
||||
SHOW_EXPR(watch(pool).cntFree())
|
||||
SHOW_EXPR(watch(pool).getMaxScore())
|
||||
SHOW_EXPR(watch(pool).getTurnover())
|
||||
SHOW_EXPR(show(usedBuff));
|
||||
CHECK ( 7 == watch(pool).size() );
|
||||
CHECK ( 6 == watch(pool).cntFree() );
|
||||
CHECK (20 == watch(pool).getMaxScore() );
|
||||
CHECK ( 2 == watch(pool).getTurnover() );
|
||||
|
||||
CHECK (pool.shouldCleanup());
|
||||
// triggering now, since 20/MATCH_SCORE ≡ 2
|
||||
|
||||
SHOW_EXPR(pool.shouldCleanup())
|
||||
removed = pool.cleanup(0.5, pushMem);
|
||||
SHOW_EXPR(removed)
|
||||
CHECK (3 == removed);
|
||||
CHECK (show(globalPool) == "11, 12, 21"_expect);
|
||||
|
||||
SHOW_EXPR(watch(pool).size())
|
||||
SHOW_EXPR(watch(pool).getMaxScore())
|
||||
SHOW_EXPR(watch(pool).getTurnover())
|
||||
SHOW_EXPR(show(globalPool));
|
||||
CHECK ( 4 == watch(pool).size() );
|
||||
CHECK ( 3 == watch(pool).cntFree() );
|
||||
CHECK (10 == watch(pool).getMaxScore() );
|
||||
CHECK ( 4 == watch(pool).getTurnover() );
|
||||
|
||||
|
||||
//------------ PATTERN-4 : decreasing the fraction used
|
||||
claim(1);
|
||||
|
||||
SHOW_EXPR("claim")
|
||||
SHOW_EXPR(watch(pool).size())
|
||||
SHOW_EXPR(watch(pool).cntFree())
|
||||
SHOW_EXPR(watch(pool).cntResd())
|
||||
SHOW_EXPR(watch(pool).getMaxScore())
|
||||
SHOW_EXPR(watch(pool).getTurnover())
|
||||
CHECK ( 4 == watch(pool).size() );
|
||||
CHECK ( 2 == watch(pool).cntFree() );
|
||||
CHECK (20 == watch(pool).getMaxScore() );
|
||||
CHECK ( 4 == watch(pool).getTurnover() );
|
||||
|
||||
free(2);
|
||||
|
||||
SHOW_EXPR("free")
|
||||
SHOW_EXPR(watch(pool).size())
|
||||
SHOW_EXPR(watch(pool).cntFree())
|
||||
SHOW_EXPR(watch(pool).getMaxScore())
|
||||
SHOW_EXPR(watch(pool).getTurnover())
|
||||
CHECK ( 4 == watch(pool).size() );
|
||||
CHECK ( 4 == watch(pool).cntFree() );
|
||||
CHECK (20 == watch(pool).getMaxScore() );
|
||||
CHECK ( 2 == watch(pool).getTurnover() );
|
||||
|
||||
CHECK (pool.shouldCleanup() );
|
||||
|
||||
SHOW_EXPR(pool.shouldCleanup())
|
||||
removed = pool.cleanup(0.5, pushMem);
|
||||
SHOW_EXPR(removed)
|
||||
CHECK (3 == removed);
|
||||
CHECK (show(globalPool) == "11, 12, 21, 33, 31, 13"_expect);
|
||||
|
||||
SHOW_EXPR(watch(pool).size())
|
||||
SHOW_EXPR(watch(pool).getMaxScore())
|
||||
SHOW_EXPR(watch(pool).getTurnover())
|
||||
SHOW_EXPR(show(globalPool));
|
||||
CHECK ( 1 == watch(pool).size() );
|
||||
CHECK (10 == watch(pool).getMaxScore() );
|
||||
CHECK ( 1 == watch(pool).getTurnover() );
|
||||
}
|
||||
|
||||
};
|
||||
|
|
|
|||
|
|
@ -145325,7 +145325,7 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension)
|
|||
</node>
|
||||
</node>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1778802491003" ID="ID_1880673250" MODIFIED="1778979225756" TEXT="brauche noch einen Trigger-Mechanismus für das heuristische Clean-up">
|
||||
<node BACKGROUND_COLOR="#c8c0b6" COLOR="#435e98" CREATED="1778802491003" ID="ID_1880673250" MODIFIED="1779762406992" TEXT="brauche noch einen Trigger-Mechanismus für das heuristische Clean-up">
|
||||
<icon BUILTIN="yes"/>
|
||||
<node CREATED="1778805833301" ID="ID_493965127" MODIFIED="1778806330596" TEXT="man könnte nach jeder de-Allokation einen partiellen clean-up machen">
|
||||
<node CREATED="1778805853860" ID="ID_1555068699" MODIFIED="1778806001396" TEXT="wäre wirksam, da nur unterhalb der Schwelle aufgeräumt wird">
|
||||
|
|
@ -145412,7 +145412,7 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension)
|
|||
<node CREATED="1778946963640" ID="ID_993736225" MODIFIED="1778946997115" TEXT="bei Leerlauf wächst der Score weniger Blöcke (und damit der Max-Score) überproportional"/>
|
||||
<node CREATED="1778807937581" ID="ID_1900765984" MODIFIED="1778807970854" TEXT="bei lokaler Knappheit werden viele Allokations-Anforderungen gesandt"/>
|
||||
</node>
|
||||
<node CREATED="1778945962154" ID="ID_535774391" MODIFIED="1778945972518" TEXT="daraus einen Mechanismus entwickeln">
|
||||
<node COLOR="#435e98" CREATED="1778945962154" ID="ID_535774391" MODIFIED="1779762420870" TEXT="daraus einen Mechanismus entwickeln">
|
||||
<icon BUILTIN="idea"/>
|
||||
<node CREATED="1778946005609" ID="ID_1483973980" MODIFIED="1778946757293" TEXT="Ansatz: die bereits implementierte Aufräum-Heuristik ist zielführend">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
|
|
@ -145482,9 +145482,9 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension)
|
|||
</node>
|
||||
</node>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1778800559849" ID="ID_1776275235" MODIFIED="1778800646883" TEXT="LocalBufferStore_test">
|
||||
<icon BUILTIN="pencil"/>
|
||||
<node BACKGROUND_COLOR="#fdfdcf" COLOR="#ff0000" CREATED="1778800660632" ID="ID_864970874" MODIFIED="1778979160301" TEXT="Zweck">
|
||||
<node COLOR="#338800" CREATED="1778800559849" ID="ID_1776275235" MODIFIED="1779762439896" TEXT="LocalBufferStore_test">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
<node COLOR="#435e98" CREATED="1778800660632" ID="ID_864970874" MODIFIED="1779762437163" TEXT="Zweck">
|
||||
<icon BUILTIN="yes"/>
|
||||
<node CREATED="1778800664656" ID="ID_690903258" MODIFIED="1778800678906" TEXT="Aufbau der Implemenrierung treiben"/>
|
||||
<node CREATED="1778800684264" ID="ID_1722512715" MODIFIED="1778800718145" TEXT="korrektes Verhalten auf API-Level zeigen"/>
|
||||
|
|
@ -145668,9 +145668,13 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension)
|
|||
</node>
|
||||
</node>
|
||||
</node>
|
||||
<node CREATED="1778968918381" ID="ID_752345967" MODIFIED="1778968922655" TEXT="verify_release">
|
||||
<node COLOR="#338800" CREATED="1778968918381" ID="ID_752345967" MODIFIED="1779762376165" TEXT="verify_release">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
<node CREATED="1778969042432" ID="ID_1262962638" MODIFIED="1778969052166" TEXT="hier sollte auch ein clean-up provoziert werden"/>
|
||||
<node CREATED="1779665675415" ID="ID_1685534215" MODIFIED="1779665691018" TEXT="zu zeigen ist daß dieser Clean-up mit Rücksendung stattfindet"/>
|
||||
<node BACKGROUND_COLOR="#c8c0b6" COLOR="#435e98" CREATED="1779665675415" ID="ID_1685534215" MODIFIED="1779762386504" TEXT="zu zeigen ist daß dieser Clean-up mit Rücksendung stattfindet">
|
||||
<linktarget COLOR="#1b26b8" DESTINATION="ID_1685534215" ENDARROW="Default" ENDINCLINATION="408;19;" ID="Arrow_ID_1702718350" SOURCE="ID_1035469430" STARTARROW="None" STARTINCLINATION="577;30;"/>
|
||||
<icon BUILTIN="yes"/>
|
||||
</node>
|
||||
</node>
|
||||
<node COLOR="#5b280f" CREATED="1778969102656" ID="ID_249806133" MODIFIED="1779664543753" TEXT="verify_heuristic">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
|
|
@ -145688,8 +145692,8 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension)
|
|||
</html>
|
||||
</richcontent>
|
||||
<icon BUILTIN="button_cancel"/>
|
||||
<node CREATED="1779664546343" HGAP="25" ID="ID_453821075" MODIFIED="1779665655342" TEXT="dieser Test gehört zum LocalMemPool" VSHIFT="18">
|
||||
<arrowlink COLOR="#765294" DESTINATION="ID_1242239297" ENDARROW="Default" ENDINCLINATION="-1163;-399;" ID="Arrow_ID_1851213418" STARTARROW="None" STARTINCLINATION="-413;30;"/>
|
||||
<node CREATED="1779664546343" HGAP="25" ID="ID_453821075" MODIFIED="1779762367351" TEXT="dieser Test gehört zum LocalMemPool" VSHIFT="18">
|
||||
<arrowlink COLOR="#333263" DESTINATION="ID_1242239297" ENDARROW="Default" ENDINCLINATION="-1163;-399;" ID="Arrow_ID_1851213418" STARTARROW="None" STARTINCLINATION="-413;30;"/>
|
||||
<icon BUILTIN="yes"/>
|
||||
</node>
|
||||
</node>
|
||||
|
|
@ -145755,15 +145759,18 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension)
|
|||
</body>
|
||||
</html></richcontent>
|
||||
</node>
|
||||
<node CREATED="1776605858192" ID="ID_563549971" MODIFIED="1776605951752" TEXT="bleibe aber bei dem Namen — weil er klar ist">
|
||||
<node CREATED="1776605858192" ID="ID_563549971" MODIFIED="1779762245934" TEXT="bleibe aber bei dem Namen — weil er klar ist">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head/>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<p>
|
||||
das hier ist keine generische Library, sondern ein Application-Framework. Auch »Vault« ist inhaltlich genau auf Lumiera ausgerichtet, der Unterschied liegt nur im Grad der Integration mit Application-level Services
|
||||
</p>
|
||||
</body>
|
||||
</html></richcontent>
|
||||
</html>
|
||||
</richcontent>
|
||||
</node>
|
||||
<node COLOR="#338800" CREATED="1776611511064" ID="ID_419155046" MODIFIED="1776639433744" TEXT="Mutex-Locking einführen">
|
||||
<linktarget COLOR="#4ff278" DESTINATION="ID_419155046" ENDARROW="Default" ENDINCLINATION="1269;0;" ID="Arrow_ID_703288918" SOURCE="ID_808614387" STARTARROW="None" STARTINCLINATION="1269;0;"/>
|
||||
|
|
@ -147000,8 +147007,9 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension)
|
|||
<arrowlink COLOR="#f2ddc1" DESTINATION="ID_1195705832" ENDARROW="Default" ENDINCLINATION="16;47;" ID="Arrow_ID_296050493" STARTARROW="None" STARTINCLINATION="85;12;"/>
|
||||
<icon BUILTIN="button_cancel"/>
|
||||
</node>
|
||||
<node CREATED="1778969102656" ID="ID_1242239297" MODIFIED="1779665655342" TEXT="verify_heuristic">
|
||||
<linktarget COLOR="#765294" DESTINATION="ID_1242239297" ENDARROW="Default" ENDINCLINATION="-1163;-399;" ID="Arrow_ID_1851213418" SOURCE="ID_453821075" STARTARROW="None" STARTINCLINATION="-413;30;"/>
|
||||
<node COLOR="#338800" CREATED="1778969102656" ID="ID_1242239297" MODIFIED="1779762145111" TEXT="verify_heuristic">
|
||||
<linktarget COLOR="#333263" DESTINATION="ID_1242239297" ENDARROW="Default" ENDINCLINATION="-1163;-399;" ID="Arrow_ID_1851213418" SOURCE="ID_453821075" STARTARROW="None" STARTINCLINATION="-413;30;"/>
|
||||
<icon BUILTIN="button_ok"/>
|
||||
<node CREATED="1778979230293" ID="ID_1129342480" MODIFIED="1779664866045" TEXT="meine Idee der Heuristik umsetzen">
|
||||
<arrowlink COLOR="#4d5f6c" DESTINATION="ID_1141255727" ENDARROW="Default" ENDINCLINATION="-376;22;" ID="Arrow_ID_514664149" STARTARROW="None" STARTINCLINATION="-76;-210;"/>
|
||||
</node>
|
||||
|
|
@ -147037,8 +147045,23 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension)
|
|||
<node CREATED="1779733348313" ID="ID_1867741071" MODIFIED="1779733353992" TEXT="wechselnd partiell verwenden"/>
|
||||
</node>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1778979252922" ID="ID_155080806" MODIFIED="1779733388847" TEXT="Verhalten sollte deterministisch sein und Erwartung entsprechen">
|
||||
<icon BUILTIN="pencil"/>
|
||||
<node COLOR="#338800" CREATED="1778979252922" ID="ID_155080806" MODIFIED="1779762143255" TEXT="Verhalten sollte deterministisch sein und Erwartung entsprechen">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#c8c0b6" COLOR="#435e98" CREATED="1779762175999" ID="ID_1035469430" MODIFIED="1779762350703" TEXT="Clean-up ist auch in globaler Kommunikation sichtbar">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<p>
|
||||
Wenn man eine größere Kapazität reserviert, aber dann wiederholt immer nur einzelne Buffer belegt und wieder freigibt, sollte relativ bald der lokale Pool getrimmt werden, und die freigegebenen Buffer an den globaeln Pool zurückgessend
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
<arrowlink COLOR="#1b26b8" DESTINATION="ID_1685534215" ENDARROW="Default" ENDINCLINATION="408;19;" ID="Arrow_ID_1702718350" STARTARROW="None" STARTINCLINATION="577;30;"/>
|
||||
<icon BUILTIN="yes"/>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
|
|
|
|||
Loading…
Reference in a new issue