Scheduler-test: complete instrumentation helper
Verify proper operation under pressure using a multithreaded stress test
This commit is contained in:
parent
d0c1017580
commit
580c1f1f68
5 changed files with 94 additions and 25 deletions
|
|
@ -48,11 +48,9 @@
|
|||
#define LIB_INCIDENCE_COUNT_H
|
||||
|
||||
|
||||
//#include "lib/meta/function.hpp"
|
||||
#include "lib/nocopy.hpp"
|
||||
#include "lib/iter-explorer.hpp"
|
||||
|
||||
//#include <utility>
|
||||
#include <cstdint>
|
||||
#include <atomic>
|
||||
#include <vector>
|
||||
|
|
@ -63,7 +61,6 @@
|
|||
|
||||
namespace lib {
|
||||
|
||||
// using std::forward;
|
||||
using std::vector;
|
||||
|
||||
/**
|
||||
|
|
@ -211,7 +208,7 @@ namespace lib {
|
|||
|
||||
|
||||
/**
|
||||
* Visit all data captured thus far, construct a unified timeline
|
||||
* Visit all data captured thus far, construct an unified timeline
|
||||
* and then compute statistics evaluations to characterise observations.
|
||||
* @warning caller must ensure there was a barrier or visibility sync before invocation.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -146,10 +146,10 @@ namespace test{
|
|||
* @remarks - the subject function will be _copied_ into each thread
|
||||
* - so `nThreads` copies of this function will run in parallel
|
||||
* - consider locking if this function accesses a shared closure.
|
||||
* - if you pass a lambda, it is eligible for inlining followed
|
||||
* by loop optimisation -- be sure to include some action, like
|
||||
* e.g. accessing a volatile variable, to prevent the compiler
|
||||
* from entirely optimising it away altogether.
|
||||
* - if you pass a lambda, it is eligible for inlining followed by
|
||||
* loop optimisation -- be sure to include an observable effect,
|
||||
* like returning a value tied to the actual computation, to
|
||||
* prevent the compiler from optimising it away altogether.
|
||||
*/
|
||||
template<size_t nThreads, class FUN>
|
||||
inline auto
|
||||
|
|
|
|||
|
|
@ -424,7 +424,7 @@ return: 0
|
|||
END
|
||||
|
||||
|
||||
PLANNED "Instrumentation: concurrent calls" IncidenceCount_test <<END
|
||||
TEST "Instrumentation: concurrent calls" IncidenceCount_test <<END
|
||||
return: 0
|
||||
END
|
||||
|
||||
|
|
|
|||
|
|
@ -32,11 +32,9 @@
|
|||
#include "lib/thread.hpp"
|
||||
#include "lib/util.hpp"
|
||||
|
||||
//#include <string>
|
||||
#include <thread>
|
||||
|
||||
|
||||
//using std::string;
|
||||
using util::isLimited;
|
||||
using std::this_thread::sleep_for;
|
||||
using std::chrono_literals::operator ""ms;
|
||||
|
|
@ -57,9 +55,11 @@ namespace test{
|
|||
|
||||
|
||||
|
||||
/***************************************************************************//**
|
||||
* @test verifies capturing and restoring of std::ostream formatting state.
|
||||
* @see ios-savepoint.hpp
|
||||
/***************************************************************//**
|
||||
* @test verify recording and evaluation of concurrent invocations
|
||||
* of a piece of code instrumented for investigation.
|
||||
* @see incidence-count.hpp
|
||||
* @see vault::gear::TestChainLoad::ScheduleCtx
|
||||
*/
|
||||
class IncidenceCount_test
|
||||
: public Test
|
||||
|
|
@ -168,7 +168,7 @@ SHOW_EXPR(stat.timeThread(1));
|
|||
}
|
||||
|
||||
|
||||
/** @test TODO verify observation of concurrency degree
|
||||
/** @test verify observation of concurrency degree
|
||||
* @todo WIP 2/24 ✔ define ⟶ ✔ implement
|
||||
*/
|
||||
void
|
||||
|
|
@ -260,17 +260,18 @@ SHOW_EXPR(stat.timeAtConc(3));
|
|||
|
||||
|
||||
/** @test TODO verify thread-safe operation under pressure
|
||||
* @todo WIP 2/24 🔁 define ⟶ implement
|
||||
* @todo WIP 2/24 ✔ define ⟶ ✔ implement
|
||||
*/
|
||||
void
|
||||
perform_multithreadStressTest()
|
||||
{
|
||||
MARK_TEST_FUN
|
||||
const size_t CONCURR = std::thread::hardware_concurrency();
|
||||
constexpr size_t CONCURR = 16;
|
||||
const size_t REPETITIONS = 100;
|
||||
|
||||
IncidenceCount watch;
|
||||
watch.expectThreads(CONCURR)
|
||||
.expectIncidents(5000);
|
||||
.expectIncidents(10000);
|
||||
|
||||
auto act = [&]{ // two nested activities with random delay
|
||||
uint delay = 100 + rand() % 800;
|
||||
|
|
@ -282,6 +283,77 @@ SHOW_EXPR(stat.timeAtConc(3));
|
|||
watch.markLeave();
|
||||
};
|
||||
|
||||
auto [runTime, sum] = test::threadBenchmark<CONCURR> (act, REPETITIONS);
|
||||
SHOW_EXPR(runTime)
|
||||
SHOW_EXPR(sum)
|
||||
CHECK (1600 == sum);
|
||||
CHECK (isLimited (900, runTime, 1400)); // delay is 500µs on average
|
||||
|
||||
auto stat = watch.evaluate();
|
||||
SHOW_EXPR(stat.cumulatedTime);
|
||||
SHOW_EXPR(stat.activeTime);
|
||||
SHOW_EXPR(stat.coveredTime);
|
||||
CHECK (isLimited (900*REPETITIONS, stat.coveredTime, 1400*REPETITIONS));
|
||||
CHECK (stat.activeTime > 900 * REPETITIONS * CONCURR);
|
||||
SHOW_EXPR(stat.eventCnt);
|
||||
SHOW_EXPR(stat.activationCnt);
|
||||
CHECK (stat.activationCnt == 2*REPETITIONS*CONCURR);
|
||||
SHOW_EXPR(stat.cntCase(0));
|
||||
CHECK (stat.cntCase(0) == REPETITIONS*CONCURR);
|
||||
SHOW_EXPR(stat.cntCase(1));
|
||||
CHECK (stat.cntCase(1) == 0);
|
||||
SHOW_EXPR(stat.cntCase(2));
|
||||
CHECK (stat.cntCase(2) == REPETITIONS*CONCURR);
|
||||
SHOW_EXPR(stat.cntCase(3));
|
||||
SHOW_EXPR(stat.timeCase(0));
|
||||
SHOW_EXPR(stat.timeCase(1));
|
||||
SHOW_EXPR(stat.timeCase(2));
|
||||
SHOW_EXPR(stat.timeCase(3));
|
||||
SHOW_EXPR(stat.cntThread(0));
|
||||
SHOW_EXPR(stat.cntThread(1));
|
||||
SHOW_EXPR(stat.cntThread(2));
|
||||
SHOW_EXPR(stat.cntThread(3));
|
||||
SHOW_EXPR(stat.cntThread(4));
|
||||
SHOW_EXPR(stat.cntThread(5));
|
||||
SHOW_EXPR(stat.cntThread(6));
|
||||
SHOW_EXPR(stat.cntThread(7));
|
||||
SHOW_EXPR(stat.cntThread(8));
|
||||
SHOW_EXPR(stat.cntThread(9));
|
||||
SHOW_EXPR(stat.timeThread(0));
|
||||
SHOW_EXPR(stat.timeThread(1));
|
||||
SHOW_EXPR(stat.timeThread(2));
|
||||
SHOW_EXPR(stat.timeThread(3));
|
||||
SHOW_EXPR(stat.timeThread(4));
|
||||
SHOW_EXPR(stat.timeThread(5));
|
||||
SHOW_EXPR(stat.timeThread(6));
|
||||
SHOW_EXPR(stat.timeThread(7));
|
||||
SHOW_EXPR(stat.timeThread(8));
|
||||
SHOW_EXPR(stat.timeThread(9));
|
||||
SHOW_EXPR(stat.avgConcurrency);
|
||||
CHECK (isLimited(CONCURR/2, stat.avgConcurrency, CONCURR));
|
||||
for (uint i=0; i<CONCURR; ++i)
|
||||
CHECK (isLimited(REPETITIONS*900, stat.timeThread(i), REPETITIONS*1400));
|
||||
CHECK (0 == stat.timeThread(CONCURR));
|
||||
CHECK (0 == stat.timeAtConc(CONCURR+1));
|
||||
SHOW_EXPR(stat.timeAtConc(0));
|
||||
SHOW_EXPR(stat.timeAtConc(1));
|
||||
SHOW_EXPR(stat.timeAtConc(2));
|
||||
SHOW_EXPR(stat.timeAtConc(3));
|
||||
SHOW_EXPR(stat.timeAtConc(4));
|
||||
SHOW_EXPR(stat.timeAtConc(5));
|
||||
SHOW_EXPR(stat.timeAtConc(6));
|
||||
SHOW_EXPR(stat.timeAtConc(7));
|
||||
SHOW_EXPR(stat.timeAtConc(8));
|
||||
SHOW_EXPR(stat.timeAtConc(9));
|
||||
SHOW_EXPR(stat.timeAtConc(10));
|
||||
SHOW_EXPR(stat.timeAtConc(11));
|
||||
SHOW_EXPR(stat.timeAtConc(12));
|
||||
SHOW_EXPR(stat.timeAtConc(13));
|
||||
SHOW_EXPR(stat.timeAtConc(14));
|
||||
SHOW_EXPR(stat.timeAtConc(15));
|
||||
SHOW_EXPR(stat.timeAtConc(16));
|
||||
SHOW_EXPR(stat.timeAtConc(17));
|
||||
CHECK (isLimited(REPETITIONS*900, stat.timeAtConc(CONCURR), REPETITIONS*1200));
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -110970,7 +110970,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200<br/>
|
|||
<node CREATED="1707753850583" ID="ID_974443691" MODIFIED="1707753886880" TEXT="beide Instrumentierungen kann man hier gemeinsam machen">
|
||||
<icon BUILTIN="idea"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1707753869910" ID="ID_467789923" MODIFIED="1707754986603" TEXT="das ist eine generische Aufgabe: ein IncidenceCount">
|
||||
<node COLOR="#435e98" CREATED="1707753869910" ID="ID_467789923" MODIFIED="1707940141857" TEXT="das ist eine generische Aufgabe: ein IncidenceCount">
|
||||
<icon BUILTIN="yes"/>
|
||||
<node CREATED="1707753910239" ID="ID_207246442" MODIFIED="1707754952005" TEXT="Spezifikation">
|
||||
<icon BUILTIN="info"/>
|
||||
|
|
@ -111012,8 +111012,8 @@ Date:   Thu Apr 20 18:53:17 2023 +0200<br/>
|
|||
<node CREATED="1707754394399" ID="ID_85130376" MODIFIED="1707754441263" TEXT="∅ Parallellität"/>
|
||||
</node>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1707754450711" ID="ID_910369325" MODIFIED="1707768337328" TEXT="Implementierung">
|
||||
<icon BUILTIN="pencil"/>
|
||||
<node COLOR="#338800" CREATED="1707754450711" ID="ID_910369325" MODIFIED="1707940108849" TEXT="Implementierung">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
<node COLOR="#338800" CREATED="1707754455351" ID="ID_1263178646" MODIFIED="1707765868713" TEXT="Rahmen">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
<node COLOR="#338800" CREATED="1707754460590" ID="ID_1078644826" MODIFIED="1707765871131" TEXT="Lib-Implementierung">
|
||||
|
|
@ -111099,8 +111099,8 @@ Date:   Thu Apr 20 18:53:17 2023 +0200<br/>
|
|||
</node>
|
||||
</node>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1707754958979" ID="ID_284055307" MODIFIED="1707880406370" TEXT="IncidenceCount_test">
|
||||
<icon BUILTIN="pencil"/>
|
||||
<node COLOR="#338800" CREATED="1707754958979" ID="ID_284055307" MODIFIED="1707940107143" TEXT="IncidenceCount_test">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
<node COLOR="#338800" CREATED="1707754993819" ID="ID_1476552932" MODIFIED="1707770394988" TEXT="demonstrate_simpleUsage">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
</node>
|
||||
|
|
@ -111110,8 +111110,8 @@ Date:   Thu Apr 20 18:53:17 2023 +0200<br/>
|
|||
<node COLOR="#338800" CREATED="1707880388944" ID="ID_1618021077" MODIFIED="1707880390672" TEXT="verify_concurrencyStatistic">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1707755017591" ID="ID_464212476" MODIFIED="1707880399746" TEXT="perform_multithreadStressTest">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
<node COLOR="#338800" CREATED="1707755017591" ID="ID_464212476" MODIFIED="1707940098750" TEXT="perform_multithreadStressTest">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
|
|
|
|||
Loading…
Reference in a new issue