A Discrete-Event Network Simulator
API
bench-packets.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 // This program can be used to benchmark packet serialization/deserialization
22 // operations using Headers and Tags, for various numbers of packets 'n'
23 // Sample usage: ./waf --run 'bench-packets --n=10000'
24 
25 #include "ns3/command-line.h"
26 #include "ns3/system-wall-clock-ms.h"
27 #include "ns3/packet.h"
28 #include "ns3/packet-metadata.h"
29 #include <iostream>
30 #include <sstream>
31 #include <string>
32 #include <stdlib.h> // for exit ()
33 #include <limits>
34 #include <algorithm>
35 
36 using namespace ns3;
37 
39 template <int N>
40 class BenchHeader : public Header
41 {
42 public:
43  BenchHeader ();
51  bool IsOk (void) const;
52 
57  static TypeId GetTypeId (void);
58  virtual TypeId GetInstanceTypeId (void) const;
59  virtual void Print (std::ostream &os) const;
60  virtual uint32_t GetSerializedSize (void) const;
61  virtual void Serialize (Buffer::Iterator start) const;
62  virtual uint32_t Deserialize (Buffer::Iterator start);
63 private:
68  static std::string GetTypeName (void);
69  bool m_ok;
70 };
71 
72 template <int N>
74  : m_ok (false)
75 {}
76 
77 template <int N>
78 bool
80 {
81  return m_ok;
82 }
83 
84 template <int N>
85 std::string
87 {
88  std::ostringstream oss;
89  oss << "ns3::BenchHeader<" << N << ">";
90  return oss.str ();
91 }
92 
93 template <int N>
94 TypeId
96 {
97  static TypeId tid = TypeId (GetTypeName ().c_str ())
98  .SetParent<Header> ()
99  .SetGroupName ("Utils")
100  .HideFromDocumentation ()
101  .AddConstructor<BenchHeader <N> > ()
102  ;
103  return tid;
104 }
105 template <int N>
106 TypeId
108 {
109  return GetTypeId ();
110 }
111 
112 template <int N>
113 void
114 BenchHeader<N>::Print (std::ostream &os) const
115 {
116  NS_ASSERT (false);
117 }
118 template <int N>
119 uint32_t
121 {
122  return N;
123 }
124 template <int N>
125 void
127 {
128  start.WriteU8 (N, N);
129 }
130 template <int N>
131 uint32_t
133 {
134  m_ok = true;
135  for (int i = 0; i < N; i++)
136  {
137  if (start.ReadU8 () != N)
138  {
139  m_ok = false;
140  }
141  }
142  return N;
143 }
144 
146 template <int N>
147 class BenchTag : public Tag
148 {
149 public:
154  static std::string GetName (void) {
155  std::ostringstream oss;
156  oss << "anon::BenchTag<" << N << ">";
157  return oss.str ();
158  }
163  static TypeId GetTypeId (void) {
164  static TypeId tid = TypeId (GetName ().c_str ())
165  .SetParent<Tag> ()
166  .SetGroupName ("Utils")
167  .HideFromDocumentation ()
168  .AddConstructor<BenchTag<N> > ()
169  ;
170  return tid;
171  }
172  virtual TypeId GetInstanceTypeId (void) const {
173  return GetTypeId ();
174  }
175  virtual uint32_t GetSerializedSize (void) const {
176  return N;
177  }
178  virtual void Serialize (TagBuffer buf) const {
179  for (uint32_t i = 0; i < N; ++i)
180  {
181  buf.WriteU8 (N);
182  }
183  }
184  virtual void Deserialize (TagBuffer buf) {
185  for (uint32_t i = 0; i < N; ++i)
186  {
187  buf.ReadU8 ();
188  }
189  }
190  virtual void Print (std::ostream &os) const {
191  os << "N=" << N;
192  }
194  : Tag () {}
195 };
196 
197 
198 static void
199 benchD (uint32_t n)
200 {
201  BenchHeader<25> ipv4;
202  BenchHeader<8> udp;
203  BenchTag<16> tag1;
204  BenchTag<17> tag2;
205 
206  for (uint32_t i = 0; i < n; i++) {
207  Ptr<Packet> p = Create<Packet> (2000);
208  p->AddPacketTag (tag1);
209  p->AddHeader (udp);
210  p->RemovePacketTag (tag1);
211  p->AddPacketTag (tag2);
212  p->AddHeader (ipv4);
213  Ptr<Packet> o = p->Copy ();
214  o->RemoveHeader (ipv4);
215  p->RemovePacketTag (tag2);
216  o->RemoveHeader (udp);
217  }
218 }
219 
220 
221 
222 static void
223 benchA (uint32_t n)
224 {
225  BenchHeader<25> ipv4;
226  BenchHeader<8> udp;
227 
228  // The original version of this program did not use BenchHeader::IsOK ()
229  // Below are two asserts that suggest how it can be used.
230  NS_ASSERT_MSG (ipv4.IsOk () == false, "IsOk() should be false before deserialization");
231  for (uint32_t i = 0; i < n; i++) {
232  Ptr<Packet> p = Create<Packet> (2000);
233  p->AddHeader (udp);
234  p->AddHeader (ipv4);
235  Ptr<Packet> o = p->Copy ();
236  o->RemoveHeader (ipv4);
237  o->RemoveHeader (udp);
238  }
239  NS_ASSERT_MSG (ipv4.IsOk () == true, "IsOk() should be true after deserialization");
240 }
241 
242 static void
243 benchB (uint32_t n)
244 {
245  BenchHeader<25> ipv4;
246  BenchHeader<8> udp;
247 
248  for (uint32_t i = 0; i < n; i++) {
249  Ptr<Packet> p = Create<Packet> (2000);
250  p->AddHeader (udp);
251  p->AddHeader (ipv4);
252  }
253 }
254 
255 static void
257 {
258  BenchHeader<8> udp;
259 
260  p->RemoveHeader (udp);
261 }
262 
263 static void
265 {
266  BenchHeader<25> ipv4;
267  p->RemoveHeader (ipv4);
268  C2 (p);
269 }
270 
271 static void
272 benchC (uint32_t n)
273 {
274  BenchHeader<25> ipv4;
275  BenchHeader<8> udp;
276 
277  for (uint32_t i = 0; i < n; i++) {
278  Ptr<Packet> p = Create<Packet> (2000);
279  p->AddHeader (udp);
280  p->AddHeader (ipv4);
281  C1 (p);
282  }
283 }
284 
285 static void
286 benchFragment (uint32_t n)
287 {
288  BenchHeader<25> ipv4;
289  BenchHeader<8> udp;
290 
291  for (uint32_t i= 0; i < n; i++) {
292  Ptr<Packet> p = Create<Packet> (2000);
293  p->AddHeader (udp);
294  p->AddHeader (ipv4);
295 
296  Ptr<Packet> frag0 = p->CreateFragment (0, 250);
297  Ptr<Packet> frag1 = p->CreateFragment (250, 250);
298  Ptr<Packet> frag2 = p->CreateFragment (500, 500);
299  Ptr<Packet> frag3 = p->CreateFragment (1000, 500);
300  Ptr<Packet> frag4 = p->CreateFragment (1500, 500);
301 
302  /* Mix fragments in different order */
303  frag2->AddAtEnd (frag3);
304  frag4->AddAtEnd (frag1);
305  frag2->AddAtEnd (frag4);
306  frag0->AddAtEnd (frag2);
307 
308  frag0->RemoveHeader (ipv4);
309  frag0->RemoveHeader (udp);
310  }
311 }
312 
313 static void
314 benchByteTags (uint32_t n)
315 {
316  for (uint32_t i = 0; i < n; i++)
317  {
318  Ptr<Packet> p = Create<Packet> (2000);
319  for (uint32_t j = 0; j < 100; j++)
320  {
321  BenchTag<0> tag;
322  p->AddByteTag (tag);
323  }
324  Ptr<Packet> q = Create<Packet> (1000);
325 
326  // This should trigger adjustment of all byte tags
327  q->AddAtEnd (p);
328  }
329 }
330 
331 static uint64_t
332 runBenchOneIteration (void (*bench) (uint32_t), uint32_t n)
333 {
334  SystemWallClockMs time;
335  time.Start ();
336  (*bench) (n);
337  uint64_t deltaMs = time.End ();
338  return deltaMs;
339 }
340 
341 
342 static void
343 runBench (void (*bench) (uint32_t), uint32_t n, uint32_t minIterations, char const *name)
344 {
345  uint64_t minDelay = std::numeric_limits<uint64_t>::max();
346  for (uint32_t i = 0; i < minIterations; i++)
347  {
348  uint64_t delay = runBenchOneIteration(bench, n);
349  minDelay = std::min(minDelay, delay);
350  }
351  double ps = n;
352  ps *= 1000;
353  ps /= minDelay;
354  std::cout << ps << " packets/s"
355  << " (" << minDelay << " ms elapsed)\t"
356  << name
357  << std::endl;
358 }
359 
360 int main (int argc, char *argv[])
361 {
362  uint32_t n = 0;
363  uint32_t minIterations = 1;
364  bool enablePrinting = false;
365 
367  cmd.Usage ("Benchmark Packet class");
368  cmd.AddValue ("n", "number of iterations", n);
369  cmd.AddValue ("min-iterations", "number of subiterations to minimize iteration time over", minIterations);
370  cmd.AddValue ("enable-printing", "enable packet printing", enablePrinting);
371  cmd.Parse (argc, argv);
372 
373  if (n == 0)
374  {
375  std::cerr << "Error-- number of packets must be specified " <<
376  "by command-line argument --n=(number of packets)" << std::endl;
377  exit (1);
378  }
379  std::cout << "Running bench-packets with n=" << n << std::endl;
380  std::cout << "All tests begin by adding UDP and IPv4 headers." << std::endl;
381 
382  runBench (&benchA, n, minIterations, "Copy packet, remove headers");
383  runBench (&benchB, n, minIterations, "Just add headers");
384  runBench (&benchC, n, minIterations, "Remove by func call");
385  runBench (&benchD, n, minIterations, "Intermixed add/remove headers and tags");
386  runBench (&benchFragment, n, minIterations, "Fragmentation and concatenation");
387  runBench (&benchByteTags, n, minIterations, "Benchmark byte tags");
388 
389  return 0;
390 }
Protocol header serialization and deserialization.
Definition: header.h:42
uint32_t RemoveHeader(Header &header)
Deserialize and remove the header from the internal buffer.
Definition: packet.cc:267
static void C1(Ptr< Packet > p)
virtual void Print(std::ostream &os) const
#define min(a, b)
Definition: 80211b.c:44
virtual void Serialize(Buffer::Iterator start) const
static void benchFragment(uint32_t n)
static void benchByteTags(uint32_t n)
def start()
Definition: core.py:1790
void AddPacketTag(const Tag &tag) const
Add a packet tag.
Definition: packet.cc:814
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file...
Definition: assert.h:67
virtual uint32_t Deserialize(Buffer::Iterator start)
static std::string GetName(void)
Get the bench tag name.
BenchHeader class used for benchmarking packet serialization/deserialization.
static std::string GetTypeName(void)
Get type name function.
tuple cmd
Definition: second.py:35
TAG_BUFFER_INLINE uint8_t ReadU8(void)
Definition: tag-buffer.h:195
iterator in a Buffer instance
Definition: buffer.h:98
void Usage(const std::string usage)
Supply the program usage and documentation.
Definition: command-line.cc:96
virtual uint32_t GetSerializedSize(void) const
Ptr< Packet > CreateFragment(uint32_t start, uint32_t length) const
Create a new packet which contains a fragment of the original packet.
Definition: packet.cc:227
void AddAtEnd(Ptr< const Packet > packet)
Concatenate the input packet at the end of the current packet.
Definition: packet.cc:312
Measure elapsed wall clock time in milliseconds.
#define max(a, b)
Definition: 80211b.c:45
static void benchA(uint32_t n)
virtual uint32_t GetSerializedSize(void) const
void Start(void)
Start a measure.
static uint64_t runBenchOneIteration(void(*bench)(uint32_t), uint32_t n)
static void benchD(uint32_t n)
Parse command-line arguments.
Definition: command-line.h:205
static void benchB(uint32_t n)
static TypeId GetTypeId(void)
Register this type.
Ptr< Packet > Copy(void) const
performs a COW copy of the packet.
Definition: packet.cc:121
tag a set of bytes in a packet
Definition: tag.h:36
virtual TypeId GetInstanceTypeId(void) const
Get the most derived TypeId for this Object.
Every class exported by the ns3 library is enclosed in the ns3 namespace.
virtual void Serialize(TagBuffer buf) const
TAG_BUFFER_INLINE void WriteU8(uint8_t v)
Definition: tag-buffer.h:172
static TypeId GetTypeId(void)
Register this type.
static void runBench(void(*bench)(uint32_t), uint32_t n, uint32_t minIterations, char const *name)
#define NS_ASSERT_MSG(condition, message)
At runtime, in debugging builds, if this condition is not true, the program prints the message to out...
Definition: assert.h:90
BenchTag class used for benchmarking packet serialization/deserialization.
read and write tag data
Definition: tag-buffer.h:51
void WriteU8(uint8_t data)
Definition: buffer.h:869
void AddValue(const std::string &name, const std::string &help, T &value)
Add a program argument, assigning to POD.
Definition: command-line.h:498
bool RemovePacketTag(Tag &tag)
Remove a packet tag.
Definition: packet.cc:821
void Print(ComponentCarrier cc)
virtual void Print(std::ostream &os) const
uint8_t ReadU8(void)
Definition: buffer.h:1021
void Parse(int argc, char *argv[])
Parse the program arguments.
virtual TypeId GetInstanceTypeId(void) const
Get the most derived TypeId for this Object.
static void C2(Ptr< Packet > p)
static void benchC(uint32_t n)
int64_t End(void)
Stop measuring the time since Start() was called.
bool IsOk(void) const
Returns true if the header has been deserialized and the deserialization was correct.
a unique identifier for an interface.
Definition: type-id.h:58
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:914
bool m_ok
variable to track whether deserialization succeeded
void AddHeader(const Header &header)
Add header to this packet.
Definition: packet.cc:256
void AddByteTag(const Tag &tag) const
Tag each byte included in this packet with a new byte tag.
Definition: packet.cc:781
virtual void Deserialize(TagBuffer buf)