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)
147 Simulator::Schedule(at, &
Bench::Cb,
this);
149 init = timer.
End() / 1000.0;
150 DEB(
"initialization took " << init <<
"s");
155 simu = timer.
End() / 1000.0;
156 DEB(
"run took " << simu <<
"s");
158 Simulator::Destroy();
174 Simulator::Schedule(after, &
Bench::Cb,
this);
238 template <
typename T>
264 << std::setw(
g_fwidth) << run.period);
274 Simulator::SetScheduler(factory);
279 m_scheduler +=
": insertion order: " + std::string(calRev ?
"reverse" :
"normal");
286 Bench bench(pop, total);
296 auto prime = bench.
Run();
300 for (uint64_t i = 0; i < runs; i++)
302 auto run = bench.
Run();
307 Simulator::Destroy();
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(
' '));
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 uint64_t 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());
455main(
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 CalendarSheduler", schedCal);
483 cmd.AddValue(
"calrev",
"reverse ordering in the CalendarScheduler", calRev);
484 cmd.AddValue(
"heap",
"use HeapScheduler", schedHeap);
485 cmd.AddValue(
"list",
"use ListSheduler", 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.
AttributeValue implementation for Boolean.
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.
virtual double GetValue()=0
Get the next random value drawn from the distribution.
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 Now()
create an ns3::Time instance which contains the current simulation time.
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.
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.