20 #include "ns3/core-module.h"
37 #define LOG(x) std::cout << x << std::endl
39 #define LOGME(x) LOG(g_me << x)
66 Bench(
const uint64_t population,
const uint64_t total)
67 : m_population(population),
91 m_population = population;
144 for (uint64_t i = 0; i < m_population; ++i)
149 init = timer.
End() / 1000.0;
150 DEB(
"initialization took " << init <<
"s");
155 simu = timer.
End() / 1000.0;
156 DEB(
"run took " << simu <<
"s");
160 return Result{init, simu, m_population, m_count};
166 if (m_count >= m_total)
238 template <
typename T>
255 template <
typename T>
264 << std::setw(
g_fwidth) << run.period);
277 if (m_scheduler ==
"ns3::CalendarScheduler")
279 m_scheduler +=
": insertion order: " + std::string(calRev ?
"reverse" :
"normal");
281 if (m_scheduler ==
"ns3::MapScheduler")
283 m_scheduler +=
" (default)";
286 Bench bench(pop, total);
291 m_results.reserve(runs);
296 auto prime = bench.
Run();
297 Result::Bench(prime).Log(
"prime");
300 for (uint64_t i = 0; i < runs; i++)
302 auto run = bench.
Run();
303 m_results.push_back(Result::Bench(run));
304 m_results.back().Log(i);
318 <<
"Initialization:" << std::left <<
"Simulation:");
319 LOG(std::left << std::setw(
g_fwidth) <<
"" << std::left << std::setw(
g_fwidth) <<
"Time (s)"
320 << std::left << std::setw(
g_fwidth) <<
"Rate (ev/s)" << std::left
322 <<
"Time (s)" << std::left << std::setw(
g_fwidth) <<
"Rate (ev/s)" << std::left
324 LOG(std::setfill(
'-') << std::right << std::setw(
g_fwidth) <<
" " << std::right
326 << std::right << std::setw(
g_fwidth) <<
" " << std::right
328 << std::right << std::setw(
g_fwidth) <<
" " << std::setfill(
' '));
334 if (m_results.size() < 2)
347 Result average{m_results[0]};
351 for (; n < m_results.size(); ++n)
355 const auto& run = m_results[n];
356 uint64_t count = n + 1;
358 #define ACCUMULATE(phase, field) \
359 deltaPre = run.phase.field - average.phase.field; \
360 average.phase.field += deltaPre / count; \
361 deltaPost = run.phase.field - average.phase.field; \
362 moment2.phase.field += deltaPre * deltaPost
375 {std::sqrt(moment2.init.time / n),
376 std::sqrt(moment2.init.rate / n),
377 std::sqrt(moment2.init.period / n)},
378 {std::sqrt(moment2.run.time / n),
379 std::sqrt(moment2.run.rate / n),
380 std::sqrt(moment2.run.period / n)},
383 average.
Log(
"average");
406 if (filename.empty())
408 LOG(
" Event time distribution: default exponential");
409 auto erv = CreateObject<ExponentialRandomVariable>();
419 LOG(
" Event time distribution: from stdin");
424 LOG(
" Event time distribution: from " << filename);
425 input =
new std::ifstream(filename);
429 std::vector<double> nsValues;
431 while (!input->eof())
435 auto ns = (uint64_t)(value * 1000000000);
436 nsValues.push_back(ns);
445 LOG(
" Found " << nsValues.size() <<
" entries");
446 auto drv = CreateObject<DeterministicRandomVariable>();
447 drv->SetValueArray(&nsValues[0], nsValues.size());
455 main(
int argc,
char* argv[])
457 bool allSched =
false;
458 bool schedCal =
false;
459 bool schedHeap =
false;
460 bool schedList =
false;
461 bool schedMap =
false;
462 bool schedPQ =
false;
464 uint64_t pop = 100000;
465 uint64_t total = 1000000;
467 std::string filename =
"";
471 cmd.Usage(
"Benchmark the simulator scheduler.\n"
473 "Event intervals are taken from one of:\n"
474 " an exponential distribution, with mean 100 ns,\n"
475 " an ascii file, given by the --file=\"<filename>\" argument,\n"
476 " or standard input, by the argument --file=\"-\"\n"
477 "In the case of either --file form, the input is expected\n"
478 "to be ascii, giving the relative event times in ns.\n"
480 "If no scheduler is specified the MapScheduler will be run.");
481 cmd.AddValue(
"all",
"use all schedulers", allSched);
482 cmd.AddValue(
"cal",
"use CalendarScheduler", schedCal);
483 cmd.AddValue(
"calrev",
"reverse ordering in the CalendarScheduler", calRev);
484 cmd.AddValue(
"heap",
"use HeapScheduler", schedHeap);
485 cmd.AddValue(
"list",
"use ListScheduler", schedList);
486 cmd.AddValue(
"map",
"use MapScheduler (default)", schedMap);
487 cmd.AddValue(
"pri",
"use PriorityQueue", schedPQ);
488 cmd.AddValue(
"debug",
"enable debugging output",
g_debug);
489 cmd.AddValue(
"pop",
"event population size", pop);
490 cmd.AddValue(
"total",
"total number of events to run", total);
491 cmd.AddValue(
"runs",
"number of runs", runs);
492 cmd.AddValue(
"file",
"file of relative event times", filename);
493 cmd.AddValue(
"prec",
"printed output precision",
g_fwidth);
494 cmd.Parse(argc, argv);
500 LOGME(
" Benchmark the simulator scheduler");
501 LOG(
" Event population size: " << pop);
502 LOG(
" Total events per run: " << total);
503 LOG(
" Number of runs per scheduler: " << runs);
504 DEB(
"debugging is ON");
508 schedCal = schedHeap = schedList = schedMap = schedPQ =
true;
511 if (!(schedCal || schedHeap || schedList || schedMap || schedPQ))
521 factory.SetTypeId(
"ns3::CalendarScheduler");
523 BenchSuite(factory, pop, total, runs, eventStream, calRev).
Log();
527 BenchSuite(factory, pop, total, runs, eventStream, !calRev).
Log();
532 factory.SetTypeId(
"ns3::HeapScheduler");
533 BenchSuite(factory, pop, total, runs, eventStream, calRev).
Log();
537 factory.SetTypeId(
"ns3::ListScheduler");
538 auto listTotal = total;
541 LOG(
"Running List scheduler with 1/10 total events");
544 BenchSuite(factory, pop, listTotal, runs, eventStream, calRev).
Log();
548 factory.SetTypeId(
"ns3::MapScheduler");
549 BenchSuite(factory, pop, total, runs, eventStream, calRev).
Log();
553 factory.SetTypeId(
"ns3::PriorityQueueScheduler");
554 BenchSuite(factory, pop, total, runs, eventStream, calRev).
Log();
Ptr< RandomVariableStream > GetRandomStream(std::string filename)
Create a RandomVariableStream to generate next event delays.
bool g_debug
Flag to write debugging output.
#define LOGME(x)
Log with program name prefix.
int g_fwidth
Output field width for numeric data.
std::string g_me
Name of this program.
#define ACCUMULATE(phase, field)
#define LOG(x)
Log to std::cout.
#define DEB(x)
Log debugging output.
Benchmark instance which can do a single run.
void SetRandomStream(Ptr< RandomVariableStream > stream)
Set the event delay interval random stream.
uint64_t m_population
Event population size.
void SetTotal(const uint64_t total)
Set the total number of events to execute.
Result Run()
Run the benchmark as configured.
Ptr< RandomVariableStream > m_rand
Stream for event delays.
uint64_t m_count
Count of events executed so far.
Bench(const uint64_t population, const uint64_t total)
Constructor.
void SetPopulation(const uint64_t population)
Set the number of events to populate the scheduler with.
uint64_t m_total
Total number of events to execute.
Benchmark which performs an ensemble of runs.
void Log() const
Write the results to LOG()
BenchSuite(ObjectFactory &factory, uint64_t pop, uint64_t total, uint64_t runs, Ptr< RandomVariableStream > eventStream, bool calRev)
Perform the runs for a single scheduler type.
void Header() const
Print the table header.
std::vector< Result > m_results
Store for the run results.
std::string m_scheduler
Descriptive string for the scheduler.
Parse command-line arguments.
This class can be used to hold variables of floating point type such as 'double' or 'float'.
Instantiate subclasses of ns3::Object.
TypeId GetTypeId() const
Get the TypeId which will be created by this ObjectFactory.
static EventId Schedule(const Time &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
static void Destroy()
Execute the events scheduled with ScheduleDestroy().
static Time Now()
Return the current simulation virtual time.
static void Run()
Run the simulation.
static void SetScheduler(ObjectFactory schedulerFactory)
Set the scheduler type with an ObjectFactory.
static void Stop()
Tell the Simulator the calling event should be the last one executed.
Measure elapsed wall clock time in milliseconds.
int64_t End()
Stop measuring the time since Start() was called.
void Start()
Start a measure.
Simulation virtual time values and global simulation resolution.
std::string GetName() const
Get the name.
Time NanoSeconds(uint64_t value)
Construct a Time in the indicated unit.
Every class exported by the ns3 library is enclosed in the ns3 namespace.
SpectrumValue Log(const SpectrumValue &arg)
ns3::StringValue attribute value declarations.
uint64_t events
Number of events executed.
uint64_t pop
Event population.
double init
Time (s) for initialization.
double simu
Time (s) for simulation.
Statistics from a single phase, init or run.
double rate
Phase event rate (events/s).
double period
Phase period (s/event).
double time
Phase run time time (s).
Results from initialization and execution of a single run.
PhaseResult init
Initialization phase results.
static Result Bench(Bench::Result r)
Construct from the individual run result.
void Log(T label) const
Log this result.
PhaseResult run
Run (simulation) phase results.