BufferProvider: in preparation for a load test
To verify integration of this new engine-level facility, it seems prudent to build a load test (without going into extended stress- and performance testing). For that we need - random buffer demand - a computational load that actually uses the buffer. As part of the ''scheduler stress testing'', a self-calibrating `ComputationalLoad` was developed, which even implements both a merely computational load, but also a memory accessing computation. This can be extended to optionally use an external buffer, instead of allocating a precisely dimensioned memory block directly from heap. Obviously this extension is ''dangerous'', since there is no way to verify that the storage passed in can accommodated the storage required based on the current calibration of the `ComputationalLoad` As an aside: identified a timing check in `SchedulerService_test` that showed the tendency to fail when invoked immediately after a build.
This commit is contained in:
parent
7989e825b9
commit
ae7c9e7889
3 changed files with 19 additions and 10 deletions
|
|
@ -401,7 +401,7 @@ namespace test {
|
||||||
CHECK (activity::PASS == res); // instruction to check back once
|
CHECK (activity::PASS == res); // instruction to check back once
|
||||||
pullWork();
|
pullWork();
|
||||||
CHECK (activity::WAIT == res); // but next call will send this thread to sleep right away
|
CHECK (activity::WAIT == res); // but next call will send this thread to sleep right away
|
||||||
CHECK (delay_us < 40);
|
CHECK (delay_us < 50);
|
||||||
|
|
||||||
|
|
||||||
cout << "follow-up with some distance => follow-up delay"<<endl;
|
cout << "follow-up with some distance => follow-up delay"<<endl;
|
||||||
|
|
|
||||||
|
|
@ -87,7 +87,7 @@ namespace test {
|
||||||
|
|
||||||
|
|
||||||
/** Register this test class... */
|
/** Register this test class... */
|
||||||
LAUNCHER (SchedulerUsage_test, "unit engine");
|
LAUNCHER (SchedulerUsage_test, "integration engine");
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1324,6 +1324,7 @@ namespace test {
|
||||||
microseconds timeBase = LOAD_DEFAULT_TIME;
|
microseconds timeBase = LOAD_DEFAULT_TIME;
|
||||||
size_t sizeBase = LOAD_DEFAULT_MEM_SIZE;
|
size_t sizeBase = LOAD_DEFAULT_MEM_SIZE;
|
||||||
bool useAllocation = false;
|
bool useAllocation = false;
|
||||||
|
size_t* externalBuff{nullptr};
|
||||||
|
|
||||||
/** cause a delay by computational load */
|
/** cause a delay by computational load */
|
||||||
double
|
double
|
||||||
|
|
@ -1366,16 +1367,22 @@ namespace test {
|
||||||
return computationSpeed(false) != LOAD_SPEED_BASELINE;
|
return computationSpeed(false) != LOAD_SPEED_BASELINE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t
|
||||||
|
requiredBuffSiz (uint scaleStep) const
|
||||||
|
{
|
||||||
|
return useAllocation? allocNeeded(scaleStep).first : 0;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
uint64_t
|
uint64_t
|
||||||
roundsNeeded (uint scaleStep)
|
roundsNeeded (uint scaleStep) const
|
||||||
{
|
{
|
||||||
auto desiredMicros = scaleStep*timeBase.count();
|
auto desiredMicros = scaleStep*timeBase.count();
|
||||||
return uint64_t(desiredMicros*computationSpeed(useAllocation));
|
return uint64_t(desiredMicros*computationSpeed(useAllocation));
|
||||||
}
|
}
|
||||||
|
|
||||||
auto
|
std::pair<size_t,size_t>
|
||||||
allocNeeded (uint scaleStep)
|
allocNeeded (uint scaleStep) const
|
||||||
{
|
{
|
||||||
auto cnt = roundsNeeded(scaleStep);
|
auto cnt = roundsNeeded(scaleStep);
|
||||||
auto siz = max (scaleStep * sizeBase, 1u);
|
auto siz = max (scaleStep * sizeBase, 1u);
|
||||||
|
|
@ -1401,13 +1408,15 @@ namespace test {
|
||||||
causeMemProcessLoad (uint scaleStep)
|
causeMemProcessLoad (uint scaleStep)
|
||||||
{
|
{
|
||||||
auto [siz,round] = allocNeeded (scaleStep);
|
auto [siz,round] = allocNeeded (scaleStep);
|
||||||
lib::UninitialisedDynBlock<size_t> memBlock{siz};
|
lib::UninitialisedDynBlock<size_t> memBlock;
|
||||||
|
size_t* mem = externalBuff? externalBuff
|
||||||
|
: memBlock.allocate (siz);
|
||||||
Sink sink;
|
Sink sink;
|
||||||
*memBlock.front() = sink+1;
|
*mem = sink+1;
|
||||||
for ( ; 0 < round; --round)
|
for ( ; 0 < round; --round)
|
||||||
for (size_t i=0; i<memBlock.size()-1; ++i)
|
for (size_t i=0; i<siz-1; ++i)
|
||||||
memBlock[i+1] += memBlock[i];
|
mem[i+1] += mem[i];
|
||||||
sink = *memBlock.back();
|
sink = mem[siz-1];
|
||||||
sink = sink + 1;
|
sink = sink + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue