A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
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 
42 class Bench
43 {
44 public:
45  Bench (const uint32_t population, const uint32_t total)
46  : m_population (population),
47  m_total (total),
48  m_count (0)
49  { };
50 
52  {
53  m_rand = stream;
54  }
55 
56  void SetPopulation (const uint32_t population)
57  {
58  m_population = population;
59  }
60 
61  void SetTotal (const uint32_t total)
62  {
63  m_total = total;
64  }
65 
66  void RunBench (void);
67 private:
68  void Cb (void);
69 
71  uint32_t m_population;
72  uint32_t m_total;
73  uint32_t m_count;
74 };
75 
76 void
78 {
79  SystemWallClockMs time;
80  double init, simu;
81 
82  DEB ("initializing");
83 
84  time.Start ();
85  for (uint32_t i = 0; i < m_population; ++i)
86  {
87  Time at = NanoSeconds (m_rand->GetValue ());
88  Simulator::Schedule (at, &Bench::Cb, this);
89  }
90  init = time.End ();
91  init /= 1000;
92  DEB ("initialization took " << init << "s");
93 
94  DEB ("running");
95  time.Start ();
96  Simulator::Run ();
97  simu = time.End ();
98  simu /= 1000;
99  DEB ("run took " << simu << "s");
100 
101  LOG (std::setw (g_fwidth) << init <<
102  std::setw (g_fwidth) << (m_population / init) <<
103  std::setw (g_fwidth) << (init / m_population) <<
104  std::setw (g_fwidth) << simu <<
105  std::setw (g_fwidth) << (m_count / simu) <<
106  std::setw (g_fwidth) << (simu / m_count));
107 
108  // Clean up scheduler
110 }
111 
112 void
113 Bench::Cb (void)
114 {
115  if (m_count > m_total)
116  {
117  return;
118  }
119  DEB ("event at " << Simulator::Now ().GetSeconds () << "s");
120 
121  Time after = NanoSeconds (m_rand->GetValue ());
122  Simulator::Schedule (after, &Bench::Cb, this);
123  ++m_count;
124 }
125 
126 
128 GetRandomStream (std::string filename)
129 {
130  Ptr<RandomVariableStream> stream = 0;
131 
132  if (filename == "")
133  {
134  LOGME ("using default exponential distribution");
135  Ptr<ExponentialRandomVariable> erv = CreateObject<ExponentialRandomVariable> ();
136  erv->SetAttribute ("Mean", DoubleValue (100));
137  stream = erv;
138  }
139  else
140  {
141  std::istream *input;
142 
143  if (filename == "-")
144  {
145  LOGME ("using event distribution from stdin");
146  input = &std::cin;
147  }
148  else
149  {
150  LOGME ("using event distribution from " << filename);
151  input = new std::ifstream (filename.c_str ());
152  }
153 
154  double value;
155  std::vector<double> nsValues;
156 
157  while (!input->eof ())
158  {
159  if (*input >> value)
160  {
161  uint64_t ns = (uint64_t) (value * 1000000000);
162  nsValues.push_back (ns);
163  }
164  else
165  {
166  input->clear ();
167  std::string line;
168  *input >> line;
169  }
170  }
171  LOGME ("found " << nsValues.size () << " entries");
172  Ptr<DeterministicRandomVariable> drv = CreateObject<DeterministicRandomVariable> ();
173  drv->SetValueArray (&nsValues[0], nsValues.size ());
174  stream = drv;
175  }
176 
177  return stream;
178 }
179 
180 
181 
182 int main (int argc, char *argv[])
183 {
184 
185  bool schedCal = false;
186  bool schedHeap = false;
187  bool schedList = false;
188  bool schedMap = true;
189 
190  uint32_t pop = 100000;
191  uint32_t total = 1000000;
192  uint32_t runs = 1;
193  std::string filename = "";
194 
195  CommandLine cmd;
196  cmd.Usage ("Benchmark the simulator scheduler.\n"
197  "\n"
198  "Event intervals are taken from one of:\n"
199  " an exponential distribution, with mean 100 ns,\n"
200  " an ascii file, given by the --file=\"<filename>\" argument,\n"
201  " or standard input, by the argument --file=\"-\"\n"
202  "In the case of either --file form, the input is expected\n"
203  "to be ascii, giving the relative event times in ns.");
204  cmd.AddValue ("cal", "use CalendarSheduler", schedCal);
205  cmd.AddValue ("heap", "use HeapScheduler", schedHeap);
206  cmd.AddValue ("list", "use ListSheduler", schedList);
207  cmd.AddValue ("map", "use MapScheduler (default)", schedMap);
208  cmd.AddValue ("debug", "enable debugging output", g_debug);
209  cmd.AddValue ("pop", "event population size (default 1E5)", pop);
210  cmd.AddValue ("total", "total number of events to run (default 1E6)", total);
211  cmd.AddValue ("runs", "number of runs (default 1)", runs);
212  cmd.AddValue ("file", "file of relative event times", filename);
213  cmd.AddValue ("prec", "printed output precision", g_fwidth);
214  cmd.Parse (argc, argv);
215  g_me = cmd.GetName () + ": ";
216  g_fwidth += 6; // 5 extra chars in '2.000002e+07 ': . e+0 _
217 
218  ObjectFactory factory ("ns3::MapScheduler");
219  if (schedCal) { factory.SetTypeId ("ns3::CalendarScheduler"); }
220  if (schedHeap) { factory.SetTypeId ("ns3::HeapScheduler"); }
221  if (schedList) { factory.SetTypeId ("ns3::ListScheduler"); }
222  Simulator::SetScheduler (factory);
223 
224  LOGME (std::setprecision (g_fwidth - 6));
225  DEB ("debugging is ON");
226 
227  LOGME ("scheduler: " << factory.GetTypeId ().GetName ());
228  LOGME ("population: " << pop);
229  LOGME ("total events: " << total);
230  LOGME ("runs: " << runs);
231 
232  Bench *bench = new Bench (pop, total);
233  bench->SetRandomStream (GetRandomStream (filename));
234 
235  // table header
236  LOG ("");
237  LOG (std::left << std::setw (g_fwidth) << "Run #" <<
238  std::left << std::setw (3 * g_fwidth) << "Inititialization:" <<
239  std::left << std::setw (3 * g_fwidth) << "Simulation:");
240  LOG (std::left << std::setw (g_fwidth) << "" <<
241  std::left << std::setw (g_fwidth) << "Time (s)" <<
242  std::left << std::setw (g_fwidth) << "Rate (ev/s)" <<
243  std::left << std::setw (g_fwidth) << "Per (s/ev)" <<
244  std::left << std::setw (g_fwidth) << "Time (s)" <<
245  std::left << std::setw (g_fwidth) << "Rate (ev/s)" <<
246  std::left << std::setw (g_fwidth) << "Per (s/ev)" );
247  LOG (std::setfill ('-') <<
248  std::right << std::setw (g_fwidth) << " " <<
249  std::right << std::setw (g_fwidth) << " " <<
250  std::right << std::setw (g_fwidth) << " " <<
251  std::right << std::setw (g_fwidth) << " " <<
252  std::right << std::setw (g_fwidth) << " " <<
253  std::right << std::setw (g_fwidth) << " " <<
254  std::right << std::setw (g_fwidth) << " " <<
255  std::setfill (' ')
256  );
257 
258  // prime
259  DEB ("priming");
260  std::cout << std::left << std::setw (g_fwidth) << "(prime)";
261  bench->RunBench ();
262 
263  bench->SetPopulation (pop);
264  bench->SetTotal (total);
265  for (uint32_t i = 0; i < runs; i++)
266  {
267  std::cout << std::setw (g_fwidth) << i;
268 
269  bench->RunBench ();
270  }
271 
272  LOG ("");
273  return 0;
274 }
TypeId GetTypeId(void) const
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:79
Ptr< RandomVariableStream > m_rand
void RunBench(void)
static void Run(void)
Run the simulation until one of:
Definition: simulator.cc:157
void SetTypeId(TypeId tid)
static EventId Schedule(Time const &time, MEM mem_ptr, OBJ obj)
Schedule an event to expire at the relative time "time" is reached.
Definition: simulator.h:825
Ptr< RandomVariableStream > GetRandomStream(std::string filename)
std::string GetName() const
Get the program name.
Definition: command-line.cc:93
void Usage(const std::string usage)
Supply the program usage and documentation.
Definition: command-line.cc:87
measure elapsed time in milliseconds
#define LOGME(x)
Bench(const uint32_t population, const uint32_t total)
void SetPopulation(const uint32_t population)
uint32_t m_total
void Start(void)
Start a measure.
uint32_t m_population
Parse command-line arguments.
Definition: command-line.h:177
static void Destroy(void)
Every event scheduled by the Simulator::insertAtDestroy method is invoked.
Definition: simulator.cc:121
#define LOG(x)
int g_fwidth
std::string g_me
uint32_t m_count
int main(int argc, char *argv[])
void SetRandomStream(Ptr< RandomVariableStream > stream)
bool g_debug
std::string GetName(void) const
Definition: type-id.cc:657
static void SetScheduler(ObjectFactory schedulerFactory)
Definition: simulator.cc:143
static Time Now(void)
Return the "current simulation time".
Definition: simulator.cc:180
instantiate subclasses of ns3::Object.
void AddValue(const std::string &name, const std::string &help, T &value)
Add a program argument, assigning to POD.
Definition: command-line.h:435
void Parse(int argc, char *argv[])
Parse the program arguments.
Hold a floating point type.
Definition: double.h:41
void SetAttribute(std::string name, const AttributeValue &value)
Definition: object-base.cc:176
int64_t End(void)
Stop measuring the time since Start() was called.
void SetTotal(const uint32_t total)
void Cb(void)
#define DEB(x)