A Discrete-Event Network Simulator
API
bench-simulator.cc
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2006 INRIA
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation;
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17  *
18  * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
19  */
20 
21 #include <iomanip>
22 #include <iostream>
23 #include <fstream>
24 #include <vector>
25 #include <string.h>
26 
27 #include "ns3/core-module.h"
28 
29 using namespace ns3;
30 
31 
32 bool g_debug = false;
33 
34 std::string g_me;
35 #define LOG(x) std::cout << x << std::endl
36  #define LOGME(x) LOG (g_me << x)
37  #define DEB(x) if (g_debug) { LOGME (x); }
38 
39 // Output field width
40 int g_fwidth = 6;
41 
43 class Bench
44 {
45 public:
51  Bench (const uint32_t population, const uint32_t total)
52  : m_population (population),
53  m_total (total),
54  m_count (0)
55  {
56  }
57 
63  {
64  m_rand = stream;
65  }
66 
71  void SetPopulation (const uint32_t population)
72  {
73  m_population = population;
74  }
75 
80  void SetTotal (const uint32_t total)
81  {
82  m_total = total;
83  }
84 
86  void RunBench (void);
87 private:
89  void Cb (void);
90 
92  uint32_t m_population;
93  uint32_t m_total;
94  uint32_t m_count;
95 };
96 
97 void
99 {
100  SystemWallClockMs time;
101  double init, simu;
102 
103  DEB ("initializing");
104  m_count = 0;
105 
106 
107  time.Start ();
108  for (uint32_t i = 0; i < m_population; ++i)
109  {
110  Time at = NanoSeconds (m_rand->GetValue ());
111  Simulator::Schedule (at, &Bench::Cb, this);
112  }
113  init = time.End ();
114  init /= 1000;
115  DEB ("initialization took " << init << "s");
116 
117  DEB ("running");
118  time.Start ();
119  Simulator::Run ();
120  simu = time.End ();
121  simu /= 1000;
122  DEB ("run took " << simu << "s");
123 
124  LOG (std::setw (g_fwidth) << init <<
125  std::setw (g_fwidth) << (m_population / init) <<
126  std::setw (g_fwidth) << (init / m_population) <<
127  std::setw (g_fwidth) << simu <<
128  std::setw (g_fwidth) << (m_count / simu) <<
129  std::setw (g_fwidth) << (simu / m_count));
130 
131 }
132 
133 void
134 Bench::Cb (void)
135 {
136  if (m_count >= m_total)
137  {
138  return;
139  }
140  DEB ("event at " << Simulator::Now ().GetSeconds () << "s");
141 
142  Time after = NanoSeconds (m_rand->GetValue ());
143  Simulator::Schedule (after, &Bench::Cb, this);
144  ++m_count;
145 }
146 
147 
149 GetRandomStream (std::string filename)
150 {
151  Ptr<RandomVariableStream> stream = 0;
152 
153  if (filename == "")
154  {
155  LOGME ("using default exponential distribution");
156  Ptr<ExponentialRandomVariable> erv = CreateObject<ExponentialRandomVariable> ();
157  erv->SetAttribute ("Mean", DoubleValue (100));
158  stream = erv;
159  }
160  else
161  {
162  std::istream *input;
163 
164  if (filename == "-")
165  {
166  LOGME ("using event distribution from stdin");
167  input = &std::cin;
168  }
169  else
170  {
171  LOGME ("using event distribution from " << filename);
172  input = new std::ifstream (filename.c_str ());
173  }
174 
175  double value;
176  std::vector<double> nsValues;
177 
178  while (!input->eof ())
179  {
180  if (*input >> value)
181  {
182  uint64_t ns = (uint64_t) (value * 1000000000);
183  nsValues.push_back (ns);
184  }
185  else
186  {
187  input->clear ();
188  std::string line;
189  *input >> line;
190  }
191  }
192  LOGME ("found " << nsValues.size () << " entries");
193  Ptr<DeterministicRandomVariable> drv = CreateObject<DeterministicRandomVariable> ();
194  drv->SetValueArray (&nsValues[0], nsValues.size ());
195  stream = drv;
196  }
197 
198  return stream;
199 }
200 
201 
202 
203 int main (int argc, char *argv[])
204 {
205 
206  bool schedCal = false;
207  bool schedHeap = false;
208  bool schedList = false;
209  bool schedMap = true;
210  bool schedPriorityQueue = false;
211 
212  uint32_t pop = 100000;
213  uint32_t total = 1000000;
214  uint32_t runs = 1;
215  std::string filename = "";
216  bool calRev = false;
217 
218  CommandLine cmd (__FILE__);
219  cmd.Usage ("Benchmark the simulator scheduler.\n"
220  "\n"
221  "Event intervals are taken from one of:\n"
222  " an exponential distribution, with mean 100 ns,\n"
223  " an ascii file, given by the --file=\"<filename>\" argument,\n"
224  " or standard input, by the argument --file=\"-\"\n"
225  "In the case of either --file form, the input is expected\n"
226  "to be ascii, giving the relative event times in ns.");
227  cmd.AddValue ("cal", "use CalendarSheduler", schedCal);
228  cmd.AddValue ("calrev", "reverse ordering in the CalendarScheduler", calRev);
229  cmd.AddValue ("heap", "use HeapScheduler", schedHeap);
230  cmd.AddValue ("list", "use ListSheduler", schedList);
231  cmd.AddValue ("map", "use MapScheduler (default)", schedMap);
232  cmd.AddValue ("pri", "use PriorityQueue", schedPriorityQueue);
233  cmd.AddValue ("debug", "enable debugging output", g_debug);
234  cmd.AddValue ("pop", "event population size (default 1E5)", pop);
235  cmd.AddValue ("total", "total number of events to run (default 1E6)", total);
236  cmd.AddValue ("runs", "number of runs (default 1)", runs);
237  cmd.AddValue ("file", "file of relative event times", filename);
238  cmd.AddValue ("prec", "printed output precision", g_fwidth);
239  cmd.Parse (argc, argv);
240  g_me = cmd.GetName () + ": ";
241  g_fwidth += 6; // 5 extra chars in '2.000002e+07 ': . e+0 _
242 
243  ObjectFactory factory ("ns3::MapScheduler");
244  if (schedCal)
245  {
246  factory.SetTypeId ("ns3::CalendarScheduler");
247  factory.Set ("Reverse", BooleanValue (calRev));
248  }
249  if (schedHeap)
250  {
251  factory.SetTypeId ("ns3::HeapScheduler");
252  }
253  if (schedList)
254  {
255  factory.SetTypeId ("ns3::ListScheduler");
256  }
257  if (schedPriorityQueue)
258  {
259  factory.SetTypeId ("ns3::PriorityQueueScheduler");
260  }
261 
262  Simulator::SetScheduler (factory);
263 
264  LOGME (std::setprecision (g_fwidth - 6));
265  DEB ("debugging is ON");
266 
267  std::string order;
268  if (schedCal)
269  {
270  order = ": insertion order: " + std::string (calRev ? "reverse" : "normal");
271  }
272  LOGME ("scheduler: " << factory.GetTypeId ().GetName () << order);
273  LOGME ("population: " << pop);
274  LOGME ("total events: " << total);
275  LOGME ("runs: " << runs);
276 
277  Bench *bench = new Bench (pop, total);
278  bench->SetRandomStream (GetRandomStream (filename));
279 
280  // table header
281  LOG ("");
282  LOG (std::left << std::setw (g_fwidth) << "Run #" <<
283  std::left << std::setw (3 * g_fwidth) << "Initialization:" <<
284  std::left << std::setw (3 * g_fwidth) << "Simulation:");
285  LOG (std::left << std::setw (g_fwidth) << "" <<
286  std::left << std::setw (g_fwidth) << "Time (s)" <<
287  std::left << std::setw (g_fwidth) << "Rate (ev/s)" <<
288  std::left << std::setw (g_fwidth) << "Per (s/ev)" <<
289  std::left << std::setw (g_fwidth) << "Time (s)" <<
290  std::left << std::setw (g_fwidth) << "Rate (ev/s)" <<
291  std::left << std::setw (g_fwidth) << "Per (s/ev)" );
292  LOG (std::setfill ('-') <<
293  std::right << std::setw (g_fwidth) << " " <<
294  std::right << std::setw (g_fwidth) << " " <<
295  std::right << std::setw (g_fwidth) << " " <<
296  std::right << std::setw (g_fwidth) << " " <<
297  std::right << std::setw (g_fwidth) << " " <<
298  std::right << std::setw (g_fwidth) << " " <<
299  std::right << std::setw (g_fwidth) << " " <<
300  std::setfill (' ')
301  );
302 
303  // prime
304  DEB ("priming");
305  std::cout << std::left << std::setw (g_fwidth) << "(prime)";
306  bench->RunBench ();
307 
308  bench->SetPopulation (pop);
309  bench->SetTotal (total);
310  for (uint32_t i = 0; i < runs; i++)
311  {
312  std::cout << std::setw (g_fwidth) << i;
313 
314  bench->RunBench ();
315  }
316 
317  LOG ("");
319  delete bench;
320  return 0;
321 }
static EventId Schedule(Time const &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition: simulator.h:557
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:103
AttributeValue implementation for Boolean.
Definition: boolean.h:36
Ptr< RandomVariableStream > m_rand
random variable
void RunBench(void)
Run function.
ns3::StringValue attribute value declarations.
static void Run(void)
Run the simulation.
Definition: simulator.cc:172
cmd
Definition: second.py:35
Bench class.
Ptr< RandomVariableStream > GetRandomStream(std::string filename)
Measure elapsed wall clock time in milliseconds.
#define LOGME(x)
Bench(const uint32_t population, const uint32_t total)
constructor
void SetPopulation(const uint32_t population)
Set population function.
uint32_t m_total
total
Time NanoSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1302
void Start(void)
Start a measure.
uint32_t m_population
population
Parse command-line arguments.
Definition: command-line.h:226
static void Destroy(void)
Execute the events scheduled with ScheduleDestroy().
Definition: simulator.cc:136
#define LOG(x)
int g_fwidth
std::string g_me
Every class exported by the ns3 library is enclosed in the ns3 namespace.
uint32_t m_count
count
void SetRandomStream(Ptr< RandomVariableStream > stream)
Set random stream.
bool g_debug
static void SetScheduler(ObjectFactory schedulerFactory)
Set the scheduler type with an ObjectFactory.
Definition: simulator.cc:158
static Time Now(void)
Return the current simulation virtual time.
Definition: simulator.cc:195
Instantiate subclasses of ns3::Object.
This class can be used to hold variables of floating point type such as &#39;double&#39; or &#39;float&#39;...
Definition: double.h:41
void SetAttribute(std::string name, const AttributeValue &value)
Set a single attribute, raising fatal errors if unsuccessful.
Definition: object-base.cc:185
int64_t End(void)
Stop measuring the time since Start() was called.
void SetTotal(const uint32_t total)
Set total function.
void Cb(void)
callback function
#define DEB(x)