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:280
static void C1(Ptr< Packet > p)
virtual void Serialize(Buffer::Iterator start) const
virtual void Print(std::ostream &os) const
NS_ASSERT_MSG(false, "Ipv4AddressGenerator::MaskToIndex(): Impossible")
#define min(a, b)
Definition: 80211b.c:42
static void benchFragment(uint32_t n)
static void benchByteTags(uint32_t n)
def start()
Definition: core.py:1858
virtual void Print(std::ostream &os) 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
#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
cmd
Definition: second.py:35
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.
TAG_BUFFER_INLINE uint8_t ReadU8(void)
Definition: tag-buffer.h:195
iterator in a Buffer instance
Definition: buffer.h:98
void AddAtEnd(Ptr< const Packet > packet)
Concatenate the input packet at the end of the current packet.
Definition: packet.cc:335
Measure elapsed wall clock time in milliseconds.
#define max(a, b)
Definition: 80211b.c:43
static void benchA(uint32_t n)
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:213
static void benchB(uint32_t n)
static TypeId GetTypeId(void)
Register this type.
tag a set of bytes in a packet
Definition: tag.h:36
virtual uint32_t GetSerializedSize(void) const
Every class exported by the ns3 library is enclosed in the ns3 namespace.
virtual void Serialize(TagBuffer buf) const
Ptr< Packet > Copy(void) const
performs a COW copy of the packet.
Definition: packet.cc:121
TAG_BUFFER_INLINE void WriteU8(uint8_t v)
Definition: tag-buffer.h:172
virtual TypeId GetInstanceTypeId(void) const
Get the most derived TypeId for this Object.
static TypeId GetTypeId(void)
Register this type.
static void runBench(void(*bench)(uint32_t), uint32_t n, uint32_t minIterations, char const *name)
virtual uint32_t GetSerializedSize(void) const
BenchTag class used for benchmarking packet serialization/deserialization.
read and write tag data
Definition: tag-buffer.h:51
void AddPacketTag(const Tag &tag) const
Add a packet tag.
Definition: packet.cc:863
bool RemovePacketTag(Tag &tag)
Remove a packet tag.
Definition: packet.cc:870
void Print(ComponentCarrier cc)
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.
a unique identifier for an interface.
Definition: type-id.h:58
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:915
void AddByteTag(const Tag &tag) const
Tag each byte included in this packet with a new byte tag.
Definition: packet.cc:819
bool m_ok
variable to track whether deserialization succeeded
void AddHeader(const Header &header)
Add header to this packet.
Definition: packet.cc:256
bool IsOk(void) const
Returns true if the header has been deserialized and the deserialization was correct.
virtual void Deserialize(TagBuffer buf)