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
29using namespace ns3;
30
31
32bool g_debug = false;
33
34std::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
40int g_fwidth = 6;
41
43class Bench
44{
45public:
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);
87private:
89 void Cb (void);
90
95};
96
97void
99{
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
133void
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
149GetRandomStream (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
203int 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 ("");
318 Simulator::Destroy ();
319 delete bench;
320 return 0;
321}
Ptr< RandomVariableStream > GetRandomStream(std::string filename)
bool g_debug
#define LOGME(x)
int g_fwidth
std::string g_me
#define LOG(x)
#define DEB(x)
Bench class.
void SetRandomStream(Ptr< RandomVariableStream > stream)
Set random stream.
void RunBench(void)
Run function.
uint32_t m_count
count
void Cb(void)
callback function
void SetTotal(const uint32_t total)
Set total function.
Ptr< RandomVariableStream > m_rand
random variable
Bench(const uint32_t population, const uint32_t total)
constructor
uint32_t m_total
total
uint32_t m_population
population
void SetPopulation(const uint32_t population)
Set population function.
AttributeValue implementation for Boolean.
Definition: boolean.h:37
Parse command-line arguments.
Definition: command-line.h:229
This class can be used to hold variables of floating point type such as 'double' or 'float'.
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:256
Instantiate subclasses of ns3::Object.
virtual double GetValue(void)=0
Get the next random value as a double drawn from the distribution.
Measure elapsed wall clock time in milliseconds.
void Start(void)
Start a measure.
int64_t End(void)
Stop measuring the time since Start() was called.
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:103
Time Now(void)
create an ns3::Time instance which contains the current simulation time.
Definition: simulator.cc:287
Time NanoSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1268
Every class exported by the ns3 library is enclosed in the ns3 namespace.
cmd
Definition: second.py:35
ns3::StringValue attribute value declarations.