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 vault {
|
||||||
namespace mem {
|
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;
|
using util::_Fmt;
|
||||||
|
|
||||||
class LocalStoreDiagnostic;
|
class LocalStoreDiagnostic;
|
||||||
|
|
@ -73,16 +79,28 @@ namespace mem {
|
||||||
* This implementation of the BufferProvider::BufferStore interface
|
* This implementation of the BufferProvider::BufferStore interface
|
||||||
* deliberately skips further sanity checks, beyond what is enforced
|
* deliberately skips further sanity checks, beyond what is enforced
|
||||||
* through the BufferMetadata lifecycle. Allocation requests are
|
* 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
|
class LocalBufferStore
|
||||||
: public BufferProviderSetup::Store
|
: public BufferProviderSetup::Store
|
||||||
{
|
{
|
||||||
struct SetupPool;
|
struct PoolSetup;
|
||||||
using LocalPool = lib::LocalSlice<LocalMemPool, SetupPool>;
|
using LocalPool = lib::LocalSlice<LocalMemPool, PoolSetup>;
|
||||||
using GlobalPool = lib::Depend<EngineBufferManager>;
|
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;
|
using Service = LocalMemPool;
|
||||||
|
|
||||||
|
|
@ -91,12 +109,7 @@ namespace mem {
|
||||||
{
|
{
|
||||||
return LocalMemPool{[](LocalMemPool& pool2close)
|
return LocalMemPool{[](LocalMemPool& pool2close)
|
||||||
{
|
{
|
||||||
pool2close.purge([](Buff* mem, size_t siz)
|
pool2close.purge (send_back2globalPool);
|
||||||
{
|
|
||||||
Alloc alloc{mem,siz};
|
|
||||||
GlobalPool globalPool;
|
|
||||||
globalPool().supply(alloc);
|
|
||||||
});
|
|
||||||
}};
|
}};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -105,8 +118,7 @@ namespace mem {
|
||||||
GlobalPool globalPool_;
|
GlobalPool globalPool_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
LocalBufferStore()
|
LocalBufferStore() { }
|
||||||
{ }
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -191,15 +203,19 @@ namespace mem {
|
||||||
auto& [storage,buffSiz,specifics] = storageSlot;
|
auto& [storage,buffSiz,specifics] = storageSlot;
|
||||||
REQUIRE (storage);
|
REQUIRE (storage);
|
||||||
localPool_->reSupply (storage);
|
localPool_->reSupply (storage);
|
||||||
/////////////////////////////////////////////////////OOO trigger heuristic clean-up here
|
if (localPool_->shouldCleanup (TRIGGER_SENSITIVIY))
|
||||||
|
localPool_->cleanup (HEURISTIC_CLEANUP
|
||||||
|
,send_back2globalPool);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/** diagnostic access for unit testing */
|
/** diagnostic access for unit testing */
|
||||||
friend PoolDiagnostic watch (LocalBufferStore const&);
|
friend PoolDiagnostic watch (LocalBufferStore const&);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/** entrance point to inspection for test */
|
/** entrance point to inspection for test */
|
||||||
inline PoolDiagnostic
|
inline PoolDiagnostic
|
||||||
watch (LocalBufferStore const& lstor)
|
watch (LocalBufferStore const& lstor)
|
||||||
|
|
|
||||||
|
|
@ -205,9 +205,9 @@ namespace mem {
|
||||||
|
|
||||||
/** turnover-based trigger for heuristic pool clean-up */
|
/** turnover-based trigger for heuristic pool clean-up */
|
||||||
bool
|
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/depend-inject.hpp"
|
||||||
#include "lib/thread.hpp"
|
#include "lib/thread.hpp"
|
||||||
#include "lib/util.hpp"
|
#include "lib/util.hpp"
|
||||||
#include "test/diagnostic-output.hpp"///////////////////////TODO
|
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
|
|
@ -40,28 +39,11 @@ namespace vault {
|
||||||
namespace mem {
|
namespace mem {
|
||||||
namespace test {
|
namespace test {
|
||||||
|
|
||||||
// using LERR_(LOGIC);
|
|
||||||
// using LERR_(LIFECYCLE);
|
|
||||||
|
|
||||||
|
|
||||||
namespace { // Test helper
|
/*********************************************//**
|
||||||
|
* @test verify memory handling in worker
|
||||||
// template<typename X>
|
* that relies on a thread-local allocation pool.
|
||||||
// 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.
|
|
||||||
*/
|
*/
|
||||||
class LocalBufferStore_test : public Test
|
class LocalBufferStore_test : public Test
|
||||||
{
|
{
|
||||||
|
|
@ -69,8 +51,6 @@ namespace test {
|
||||||
virtual void
|
virtual void
|
||||||
run (Arg)
|
run (Arg)
|
||||||
{
|
{
|
||||||
// seedRand();
|
|
||||||
|
|
||||||
verify_API();
|
verify_API();
|
||||||
verify_announce();
|
verify_announce();
|
||||||
verify_allocate();
|
verify_allocate();
|
||||||
|
|
@ -372,7 +352,7 @@ namespace test {
|
||||||
/** @test heuristic clean-up after releasing several allocations
|
/** @test heuristic clean-up after releasing several allocations
|
||||||
* - at first, a de-allocated block remains available in the local pool
|
* - at first, a de-allocated block remains available in the local pool
|
||||||
* - after a number of usages, defined as _turnover_, clean-up is triggered
|
* - 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
|
* - after the third round with this usage pattern, the local pool is reduced
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
|
|
@ -394,7 +374,7 @@ namespace test {
|
||||||
Thread testWorker{[&] /* === Scenario: test subject requests allocation immediately === */
|
Thread testWorker{[&] /* === Scenario: test subject requests allocation immediately === */
|
||||||
{
|
{
|
||||||
// Step-1 : first round
|
// Step-1 : first round
|
||||||
uint avail = storeAPI.prepareBuffers(TYPEID, 3, BUFFSIZ);
|
uint avail = storeAPI.prepareBuffers(TYPEID, 5, BUFFSIZ);
|
||||||
CHECK (0 == avail);
|
CHECK (0 == avail);
|
||||||
CHECK (watch(localStore).isEmpty());
|
CHECK (watch(localStore).isEmpty());
|
||||||
|
|
||||||
|
|
@ -403,36 +383,40 @@ namespace test {
|
||||||
CHECK (storage);
|
CHECK (storage);
|
||||||
|
|
||||||
storeAPI.detachBuffer (TYPEID, slot1);
|
storeAPI.detachBuffer (TYPEID, slot1);
|
||||||
// Result: got three allocations and all three are in the local pool
|
// Result: got five allocations and all are in the local pool
|
||||||
CHECK (watch(localStore).size() == 3);
|
CHECK (watch(localStore).size() == 5);
|
||||||
CHECK (watch(localStore).cntFree() == 3);
|
CHECK (watch(localStore).cntFree() == 5);
|
||||||
|
|
||||||
++step;
|
++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);
|
BuffAlloc slot2 = storeAPI.provideBuffer (TYPEID, BUFFSIZ, 0,0);
|
||||||
CHECK (slot2 == slot1);
|
CHECK (slot2 == slot1);
|
||||||
CHECK (watch(localStore).size() == 3);
|
CHECK (watch(localStore).size() == 5);
|
||||||
CHECK (watch(localStore).cntFree() == 2);
|
CHECK (watch(localStore).cntFree() == 4);
|
||||||
|
|
||||||
storeAPI.detachBuffer (TYPEID, slot1);
|
storeAPI.detachBuffer (TYPEID, slot1);
|
||||||
CHECK (watch(localStore).size() == 3);
|
CHECK (watch(localStore).size() == 5);
|
||||||
CHECK (watch(localStore).cntFree() == 3);
|
CHECK (watch(localStore).cntFree() == 5);
|
||||||
|
|
||||||
++step;
|
++step;
|
||||||
// Step-3 : repeat for a third time
|
// Step-3 : repeat for a third time
|
||||||
BuffAlloc slot3 = storeAPI.provideBuffer (TYPEID, BUFFSIZ, 0,0);
|
BuffAlloc slot3 = storeAPI.provideBuffer (TYPEID, BUFFSIZ, 0,0);
|
||||||
CHECK (slot3 == slot1);
|
CHECK (slot3 == slot1);
|
||||||
CHECK (watch(localStore).size() == 3);
|
CHECK (watch(localStore).size() == 5);
|
||||||
CHECK (watch(localStore).cntFree() == 2);
|
CHECK (watch(localStore).cntFree() == 4);
|
||||||
|
|
||||||
storeAPI.detachBuffer (TYPEID, slot1);
|
storeAPI.detachBuffer (TYPEID, slot1);
|
||||||
// this completed a "turnover" of three buffers
|
// this triggered a clean-up and detected the unused capacity
|
||||||
SHOW_EXPR(watch(localStore).size());
|
CHECK (watch(localStore).size() == 1);
|
||||||
|
CHECK (watch(localStore).cntFree() == 1);
|
||||||
|
|
||||||
++step;
|
++step;
|
||||||
// main thread will now see the partial clean-up
|
// 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 === */
|
/* === Main thread: observe effects in the global pool === */
|
||||||
|
|
@ -440,19 +424,31 @@ namespace test {
|
||||||
// wait until Step-2
|
// wait until Step-2
|
||||||
while (step < 2)
|
while (step < 2)
|
||||||
sleep_for(1ms);
|
sleep_for(1ms);
|
||||||
CHECK (watch(*globalPool).numAllocs() == 3);
|
CHECK (watch(*globalPool).numAllocs() == 5);
|
||||||
|
|
||||||
// re-check after Step-2
|
// re-check after Step-2
|
||||||
while (step <= 2)
|
while (step <= 2)
|
||||||
sleep_for(1ms);
|
sleep_for(1ms);
|
||||||
// nothing changed; local pool operates independently
|
// 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
|
// re-check after Step-3
|
||||||
while (step <= 3)
|
while (step <= 3)
|
||||||
sleep_for(1ms);
|
sleep_for(1ms);
|
||||||
globalPool->processPendingRequests();
|
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
|
/** @test heuristic trigger mechanism for pool clean-up
|
||||||
* - use a setup where the global pool is just a queue of buffer pointers
|
* - use a setup where the global pool is just a queue of buffer pointers
|
||||||
* - create abbreviated notation to play through various scenarios
|
* - create abbreviated notation to play through various scenarios
|
||||||
|
|
@ -377,208 +378,199 @@ namespace test {
|
||||||
.feed(MEM32)
|
.feed(MEM32)
|
||||||
.feed(MEM33);
|
.feed(MEM33);
|
||||||
|
|
||||||
SHOW_EXPR(show(globalPool));
|
|
||||||
SHOW_EXPR(watch(pool).size())
|
CHECK (0 == watch(pool).size() );
|
||||||
SHOW_EXPR(watch(pool).getMaxScore())
|
CHECK (0 == watch(pool).getTurnover() );
|
||||||
SHOW_EXPR(watch(pool).getTurnover())
|
|
||||||
|
|
||||||
supply(3);
|
supply(3);
|
||||||
|
|
||||||
SHOW_EXPR("supply")
|
|
||||||
SHOW_EXPR(show(globalPool));
|
|
||||||
SHOW_EXPR(watch(pool).size())
|
|
||||||
SHOW_EXPR(watch(pool).cntFree())
|
|
||||||
|
|
||||||
reserve(2);
|
reserve(2);
|
||||||
|
|
||||||
SHOW_EXPR("reserve")
|
CHECK (3 == watch(pool).size() );
|
||||||
SHOW_EXPR(watch(pool).size())
|
CHECK (3 == watch(pool).cntFree() );
|
||||||
SHOW_EXPR(watch(pool).cntFree())
|
CHECK (2 == watch(pool).cntResd() );
|
||||||
SHOW_EXPR(watch(pool).cntResd())
|
CHECK (1 == watch(pool).getMaxScore() );
|
||||||
SHOW_EXPR(watch(pool).getMaxScore())
|
CHECK (3 == watch(pool).getTurnover() );
|
||||||
SHOW_EXPR(watch(pool).getTurnover())
|
|
||||||
|
|
||||||
|
|
||||||
|
//------------ PATTERN-1 : use complete local capacity
|
||||||
claim(3);
|
claim(3);
|
||||||
|
|
||||||
SHOW_EXPR("claim")
|
CHECK ( 3 == watch(pool).size() );
|
||||||
SHOW_EXPR(watch(pool).size())
|
CHECK ( 0 == watch(pool).cntFree() );
|
||||||
SHOW_EXPR(watch(pool).cntFree())
|
CHECK ( 0 == watch(pool).cntResd() );
|
||||||
SHOW_EXPR(watch(pool).cntResd())
|
CHECK (10 == watch(pool).getMaxScore() );
|
||||||
SHOW_EXPR(watch(pool).getMaxScore())
|
CHECK ( 3 == watch(pool).getTurnover() );
|
||||||
SHOW_EXPR(watch(pool).getTurnover())
|
|
||||||
SHOW_EXPR(show(usedBuff));
|
|
||||||
|
|
||||||
free(3);
|
free(3);
|
||||||
|
|
||||||
SHOW_EXPR("free")
|
CHECK ( 3 == watch(pool).size() );
|
||||||
SHOW_EXPR(watch(pool).size())
|
CHECK ( 3 == watch(pool).cntFree() );
|
||||||
SHOW_EXPR(watch(pool).cntFree())
|
CHECK (10 == watch(pool).getMaxScore() );
|
||||||
SHOW_EXPR(watch(pool).cntResd())
|
CHECK ( 0 == watch(pool).getTurnover() );
|
||||||
SHOW_EXPR(watch(pool).getMaxScore())
|
|
||||||
SHOW_EXPR(watch(pool).getTurnover())
|
|
||||||
SHOW_EXPR(show(usedBuff));
|
|
||||||
|
|
||||||
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);
|
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())
|
CHECK ( 3 == watch(pool).size() );
|
||||||
SHOW_EXPR(watch(pool).getMaxScore())
|
CHECK ( 5 == watch(pool).getMaxScore() );
|
||||||
SHOW_EXPR(watch(pool).getTurnover())
|
// turnover is re-set to current pool size
|
||||||
SHOW_EXPR(show(globalPool));
|
CHECK ( 3 == watch(pool).getTurnover() );
|
||||||
|
|
||||||
|
|
||||||
|
//------------ PATTERN-2 : use only one buffer a time (inefficient)
|
||||||
claim(1);
|
claim(1);
|
||||||
|
|
||||||
SHOW_EXPR("claim")
|
CHECK ( 3 == watch(pool).size() );
|
||||||
SHOW_EXPR(watch(pool).size())
|
CHECK ( 2 == watch(pool).cntFree() );
|
||||||
SHOW_EXPR(watch(pool).cntFree())
|
CHECK (15 == watch(pool).getMaxScore() );
|
||||||
SHOW_EXPR(watch(pool).cntResd())
|
CHECK ( 3 == watch(pool).getTurnover() );
|
||||||
SHOW_EXPR(watch(pool).getMaxScore())
|
|
||||||
SHOW_EXPR(watch(pool).getTurnover())
|
|
||||||
|
|
||||||
free(1);
|
free(1);
|
||||||
|
|
||||||
SHOW_EXPR("free")
|
CHECK ( 3 == watch(pool).size() );
|
||||||
SHOW_EXPR(watch(pool).size())
|
CHECK ( 3 == watch(pool).cntFree() );
|
||||||
SHOW_EXPR(watch(pool).cntFree())
|
CHECK (15 == watch(pool).getMaxScore() );
|
||||||
SHOW_EXPR(watch(pool).cntResd())
|
CHECK ( 2 == watch(pool).getTurnover() );
|
||||||
SHOW_EXPR(watch(pool).getMaxScore())
|
|
||||||
SHOW_EXPR(watch(pool).getTurnover())
|
|
||||||
|
|
||||||
SHOW_EXPR(pool.shouldCleanup())
|
// not yet hitting the trigger...
|
||||||
|
CHECK (not pool.shouldCleanup() );
|
||||||
|
|
||||||
claim(1);
|
claim(1);
|
||||||
|
|
||||||
SHOW_EXPR("claim")
|
CHECK ( 3 == watch(pool).size() );
|
||||||
SHOW_EXPR(watch(pool).size())
|
CHECK ( 2 == watch(pool).cntFree() );
|
||||||
SHOW_EXPR(watch(pool).cntFree())
|
CHECK (25 == watch(pool).getMaxScore() );
|
||||||
SHOW_EXPR(watch(pool).cntResd())
|
CHECK ( 2 == watch(pool).getTurnover() );
|
||||||
SHOW_EXPR(watch(pool).getMaxScore())
|
|
||||||
SHOW_EXPR(watch(pool).getTurnover())
|
|
||||||
|
|
||||||
free(1);
|
free(1);
|
||||||
|
|
||||||
SHOW_EXPR("free")
|
CHECK ( 3 == watch(pool).size() );
|
||||||
SHOW_EXPR(watch(pool).size())
|
CHECK ( 3 == watch(pool).cntFree() );
|
||||||
SHOW_EXPR(watch(pool).cntFree())
|
CHECK (25 == watch(pool).getMaxScore() );
|
||||||
SHOW_EXPR(watch(pool).getMaxScore())
|
CHECK ( 1 == watch(pool).getTurnover() );
|
||||||
SHOW_EXPR(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);
|
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);
|
||||||
|
|
||||||
|
CHECK ( 1 == watch(pool).size() );
|
||||||
|
CHECK ( 1 == watch(pool).cntFree() );
|
||||||
|
CHECK (13 == watch(pool).getMaxScore() );
|
||||||
|
CHECK ( 1 == watch(pool).getTurnover() );
|
||||||
|
|
||||||
SHOW_EXPR(watch(pool).size())
|
|
||||||
SHOW_EXPR(watch(pool).getMaxScore())
|
|
||||||
SHOW_EXPR(watch(pool).getTurnover())
|
|
||||||
SHOW_EXPR(show(globalPool));
|
|
||||||
|
|
||||||
|
//------------ PATTERN-3 : dynamic partially overlapping usage
|
||||||
supply(4);
|
supply(4);
|
||||||
SHOW_EXPR("supply")
|
|
||||||
SHOW_EXPR(watch(pool).size())
|
CHECK ( 5 == watch(pool).size() );
|
||||||
SHOW_EXPR(watch(pool).getMaxScore())
|
CHECK ( 5 == watch(pool).cntFree() );
|
||||||
SHOW_EXPR(watch(pool).getTurnover())
|
CHECK (13 == watch(pool).getMaxScore() );
|
||||||
SHOW_EXPR(show(globalPool));
|
CHECK ( 5 == watch(pool).getTurnover() );
|
||||||
|
// turnover was bumped +4 due to increased supply
|
||||||
|
|
||||||
claim(3);
|
claim(3);
|
||||||
|
|
||||||
SHOW_EXPR("claim")
|
CHECK ( 5 == watch(pool).size() );
|
||||||
SHOW_EXPR(watch(pool).size())
|
CHECK ( 2 == watch(pool).cntFree() );
|
||||||
SHOW_EXPR(watch(pool).cntFree())
|
CHECK (13 == watch(pool).getMaxScore() );
|
||||||
SHOW_EXPR(watch(pool).cntResd())
|
CHECK ( 5 == watch(pool).getTurnover() );
|
||||||
SHOW_EXPR(watch(pool).getMaxScore())
|
|
||||||
SHOW_EXPR(watch(pool).getTurnover())
|
|
||||||
|
|
||||||
free(2);
|
free(2);
|
||||||
|
|
||||||
SHOW_EXPR("free")
|
CHECK ( 5 == watch(pool).size() );
|
||||||
SHOW_EXPR(watch(pool).size())
|
CHECK ( 4 == watch(pool).cntFree() );
|
||||||
SHOW_EXPR(watch(pool).cntFree())
|
CHECK (13 == watch(pool).getMaxScore() );
|
||||||
SHOW_EXPR(watch(pool).cntResd())
|
CHECK ( 3 == watch(pool).getTurnover() );
|
||||||
SHOW_EXPR(watch(pool).getMaxScore())
|
|
||||||
SHOW_EXPR(watch(pool).getTurnover())
|
|
||||||
|
|
||||||
SHOW_EXPR(pool.shouldCleanup())
|
CHECK (not pool.shouldCleanup() );
|
||||||
|
// no complete turnover cycle yet
|
||||||
|
|
||||||
claim(2);
|
claim(2);
|
||||||
|
|
||||||
SHOW_EXPR("claim")
|
CHECK ( 5 == watch(pool).size() );
|
||||||
SHOW_EXPR(watch(pool).size())
|
CHECK ( 2 == watch(pool).cntFree() );
|
||||||
SHOW_EXPR(watch(pool).cntFree())
|
CHECK (20 == watch(pool).getMaxScore() );
|
||||||
SHOW_EXPR(watch(pool).cntResd())
|
CHECK ( 3 == watch(pool).getTurnover() );
|
||||||
SHOW_EXPR(watch(pool).getMaxScore())
|
|
||||||
SHOW_EXPR(watch(pool).getTurnover())
|
|
||||||
|
|
||||||
supply(4);
|
supply(4);
|
||||||
SHOW_EXPR("supply")
|
|
||||||
SHOW_EXPR(watch(pool).size())
|
CHECK ( 7 == watch(pool).size() );
|
||||||
SHOW_EXPR(watch(pool).getMaxScore())
|
CHECK ( 4 == watch(pool).cntFree() );
|
||||||
SHOW_EXPR(watch(pool).getTurnover())
|
CHECK (20 == watch(pool).getMaxScore() );
|
||||||
SHOW_EXPR(show(globalPool));
|
CHECK ( 5 == watch(pool).getTurnover() );
|
||||||
|
|
||||||
free(2);
|
free(2);
|
||||||
|
|
||||||
SHOW_EXPR("free")
|
CHECK ( 7 == watch(pool).size() );
|
||||||
SHOW_EXPR(watch(pool).size())
|
CHECK ( 6 == watch(pool).cntFree() );
|
||||||
SHOW_EXPR(watch(pool).cntFree())
|
CHECK (20 == watch(pool).getMaxScore() );
|
||||||
SHOW_EXPR(watch(pool).getMaxScore())
|
CHECK ( 3 == watch(pool).getTurnover() );
|
||||||
SHOW_EXPR(watch(pool).getTurnover())
|
|
||||||
SHOW_EXPR(show(usedBuff));
|
|
||||||
|
|
||||||
claim(1);
|
claim(1);
|
||||||
|
|
||||||
SHOW_EXPR("claim")
|
CHECK ( 7 == watch(pool).size() );
|
||||||
SHOW_EXPR(watch(pool).size())
|
CHECK ( 5 == watch(pool).cntFree() );
|
||||||
SHOW_EXPR(watch(pool).cntFree())
|
CHECK (20 == watch(pool).getMaxScore() );
|
||||||
SHOW_EXPR(watch(pool).cntResd())
|
CHECK ( 3 == watch(pool).getTurnover() );
|
||||||
SHOW_EXPR(watch(pool).getMaxScore())
|
|
||||||
SHOW_EXPR(watch(pool).getTurnover())
|
|
||||||
|
|
||||||
free(1);
|
free(1);
|
||||||
|
|
||||||
SHOW_EXPR("free")
|
CHECK ( 7 == watch(pool).size() );
|
||||||
SHOW_EXPR(watch(pool).size())
|
CHECK ( 6 == watch(pool).cntFree() );
|
||||||
SHOW_EXPR(watch(pool).cntFree())
|
CHECK (20 == watch(pool).getMaxScore() );
|
||||||
SHOW_EXPR(watch(pool).getMaxScore())
|
CHECK ( 2 == watch(pool).getTurnover() );
|
||||||
SHOW_EXPR(watch(pool).getTurnover())
|
|
||||||
SHOW_EXPR(show(usedBuff));
|
CHECK (pool.shouldCleanup());
|
||||||
|
// triggering now, since 20/MATCH_SCORE ≡ 2
|
||||||
|
|
||||||
SHOW_EXPR(pool.shouldCleanup())
|
|
||||||
removed = pool.cleanup(0.5, pushMem);
|
removed = pool.cleanup(0.5, pushMem);
|
||||||
SHOW_EXPR(removed)
|
CHECK (3 == removed);
|
||||||
|
CHECK (show(globalPool) == "11, 12, 21"_expect);
|
||||||
|
|
||||||
SHOW_EXPR(watch(pool).size())
|
CHECK ( 4 == watch(pool).size() );
|
||||||
SHOW_EXPR(watch(pool).getMaxScore())
|
CHECK ( 3 == watch(pool).cntFree() );
|
||||||
SHOW_EXPR(watch(pool).getTurnover())
|
CHECK (10 == watch(pool).getMaxScore() );
|
||||||
SHOW_EXPR(show(globalPool));
|
CHECK ( 4 == watch(pool).getTurnover() );
|
||||||
|
|
||||||
|
|
||||||
|
//------------ PATTERN-4 : decreasing the fraction used
|
||||||
claim(1);
|
claim(1);
|
||||||
|
|
||||||
SHOW_EXPR("claim")
|
CHECK ( 4 == watch(pool).size() );
|
||||||
SHOW_EXPR(watch(pool).size())
|
CHECK ( 2 == watch(pool).cntFree() );
|
||||||
SHOW_EXPR(watch(pool).cntFree())
|
CHECK (20 == watch(pool).getMaxScore() );
|
||||||
SHOW_EXPR(watch(pool).cntResd())
|
CHECK ( 4 == watch(pool).getTurnover() );
|
||||||
SHOW_EXPR(watch(pool).getMaxScore())
|
|
||||||
SHOW_EXPR(watch(pool).getTurnover())
|
|
||||||
|
|
||||||
free(2);
|
free(2);
|
||||||
|
|
||||||
SHOW_EXPR("free")
|
CHECK ( 4 == watch(pool).size() );
|
||||||
SHOW_EXPR(watch(pool).size())
|
CHECK ( 4 == watch(pool).cntFree() );
|
||||||
SHOW_EXPR(watch(pool).cntFree())
|
CHECK (20 == watch(pool).getMaxScore() );
|
||||||
SHOW_EXPR(watch(pool).getMaxScore())
|
CHECK ( 2 == watch(pool).getTurnover() );
|
||||||
SHOW_EXPR(watch(pool).getTurnover())
|
|
||||||
|
|
||||||
SHOW_EXPR(pool.shouldCleanup())
|
CHECK (pool.shouldCleanup() );
|
||||||
removed = pool.cleanup(0.5, pushMem);
|
|
||||||
SHOW_EXPR(removed)
|
|
||||||
|
|
||||||
SHOW_EXPR(watch(pool).size())
|
removed = pool.cleanup(0.5, pushMem);
|
||||||
SHOW_EXPR(watch(pool).getMaxScore())
|
CHECK (3 == removed);
|
||||||
SHOW_EXPR(watch(pool).getTurnover())
|
CHECK (show(globalPool) == "11, 12, 21, 33, 31, 13"_expect);
|
||||||
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>
|
||||||
</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"/>
|
<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="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">
|
<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="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 CREATED="1778807937581" ID="ID_1900765984" MODIFIED="1778807970854" TEXT="bei lokaler Knappheit werden viele Allokations-Anforderungen gesandt"/>
|
||||||
</node>
|
</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"/>
|
<icon BUILTIN="idea"/>
|
||||||
<node CREATED="1778946005609" ID="ID_1483973980" MODIFIED="1778946757293" TEXT="Ansatz: die bereits implementierte Aufräum-Heuristik ist zielführend">
|
<node CREATED="1778946005609" ID="ID_1483973980" MODIFIED="1778946757293" TEXT="Ansatz: die bereits implementierte Aufräum-Heuristik ist zielführend">
|
||||||
<richcontent TYPE="NOTE"><html>
|
<richcontent TYPE="NOTE"><html>
|
||||||
|
|
@ -145482,9 +145482,9 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension)
|
||||||
</node>
|
</node>
|
||||||
</node>
|
</node>
|
||||||
</node>
|
</node>
|
||||||
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1778800559849" ID="ID_1776275235" MODIFIED="1778800646883" TEXT="LocalBufferStore_test">
|
<node COLOR="#338800" CREATED="1778800559849" ID="ID_1776275235" MODIFIED="1779762439896" TEXT="LocalBufferStore_test">
|
||||||
<icon BUILTIN="pencil"/>
|
<icon BUILTIN="button_ok"/>
|
||||||
<node BACKGROUND_COLOR="#fdfdcf" COLOR="#ff0000" CREATED="1778800660632" ID="ID_864970874" MODIFIED="1778979160301" TEXT="Zweck">
|
<node COLOR="#435e98" CREATED="1778800660632" ID="ID_864970874" MODIFIED="1779762437163" TEXT="Zweck">
|
||||||
<icon BUILTIN="yes"/>
|
<icon BUILTIN="yes"/>
|
||||||
<node CREATED="1778800664656" ID="ID_690903258" MODIFIED="1778800678906" TEXT="Aufbau der Implemenrierung treiben"/>
|
<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"/>
|
<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>
|
||||||
</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="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>
|
||||||
<node COLOR="#5b280f" CREATED="1778969102656" ID="ID_249806133" MODIFIED="1779664543753" TEXT="verify_heuristic">
|
<node COLOR="#5b280f" CREATED="1778969102656" ID="ID_249806133" MODIFIED="1779664543753" TEXT="verify_heuristic">
|
||||||
<richcontent TYPE="NOTE"><html>
|
<richcontent TYPE="NOTE"><html>
|
||||||
|
|
@ -145688,8 +145692,8 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension)
|
||||||
</html>
|
</html>
|
||||||
</richcontent>
|
</richcontent>
|
||||||
<icon BUILTIN="button_cancel"/>
|
<icon BUILTIN="button_cancel"/>
|
||||||
<node CREATED="1779664546343" HGAP="25" ID="ID_453821075" MODIFIED="1779665655342" TEXT="dieser Test gehört zum LocalMemPool" VSHIFT="18">
|
<node CREATED="1779664546343" HGAP="25" ID="ID_453821075" MODIFIED="1779762367351" 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;"/>
|
<arrowlink COLOR="#333263" DESTINATION="ID_1242239297" ENDARROW="Default" ENDINCLINATION="-1163;-399;" ID="Arrow_ID_1851213418" STARTARROW="None" STARTINCLINATION="-413;30;"/>
|
||||||
<icon BUILTIN="yes"/>
|
<icon BUILTIN="yes"/>
|
||||||
</node>
|
</node>
|
||||||
</node>
|
</node>
|
||||||
|
|
@ -145755,15 +145759,18 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension)
|
||||||
</body>
|
</body>
|
||||||
</html></richcontent>
|
</html></richcontent>
|
||||||
</node>
|
</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>
|
<richcontent TYPE="NOTE"><html>
|
||||||
<head/>
|
<head>
|
||||||
|
|
||||||
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<p>
|
<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
|
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>
|
</p>
|
||||||
</body>
|
</body>
|
||||||
</html></richcontent>
|
</html>
|
||||||
|
</richcontent>
|
||||||
</node>
|
</node>
|
||||||
<node COLOR="#338800" CREATED="1776611511064" ID="ID_419155046" MODIFIED="1776639433744" TEXT="Mutex-Locking einführen">
|
<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;"/>
|
<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;"/>
|
<arrowlink COLOR="#f2ddc1" DESTINATION="ID_1195705832" ENDARROW="Default" ENDINCLINATION="16;47;" ID="Arrow_ID_296050493" STARTARROW="None" STARTINCLINATION="85;12;"/>
|
||||||
<icon BUILTIN="button_cancel"/>
|
<icon BUILTIN="button_cancel"/>
|
||||||
</node>
|
</node>
|
||||||
<node CREATED="1778969102656" ID="ID_1242239297" MODIFIED="1779665655342" TEXT="verify_heuristic">
|
<node COLOR="#338800" CREATED="1778969102656" ID="ID_1242239297" MODIFIED="1779762145111" 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;"/>
|
<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">
|
<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;"/>
|
<arrowlink COLOR="#4d5f6c" DESTINATION="ID_1141255727" ENDARROW="Default" ENDINCLINATION="-376;22;" ID="Arrow_ID_514664149" STARTARROW="None" STARTINCLINATION="-76;-210;"/>
|
||||||
</node>
|
</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 CREATED="1779733348313" ID="ID_1867741071" MODIFIED="1779733353992" TEXT="wechselnd partiell verwenden"/>
|
||||||
</node>
|
</node>
|
||||||
</node>
|
</node>
|
||||||
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1778979252922" ID="ID_155080806" MODIFIED="1779733388847" TEXT="Verhalten sollte deterministisch sein und Erwartung entsprechen">
|
<node COLOR="#338800" CREATED="1778979252922" ID="ID_155080806" MODIFIED="1779762143255" TEXT="Verhalten sollte deterministisch sein und Erwartung entsprechen">
|
||||||
<icon BUILTIN="pencil"/>
|
<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>
|
</node>
|
||||||
</node>
|
</node>
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue