A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
bench-packets.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2006 INRIA
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation;
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 *
17 * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
18 */
19
20// This program can be used to benchmark packet serialization/deserialization
21// operations using Headers and Tags, for various numbers of packets 'n'
22// Sample usage: ./ns3 run 'bench-packets --n=10000'
23
24#include "ns3/command-line.h"
25#include "ns3/packet-metadata.h"
26#include "ns3/packet.h"
27#include "ns3/system-wall-clock-ms.h"
28
29#include <algorithm>
30#include <iostream>
31#include <limits>
32#include <sstream>
33#include <stdlib.h> // for exit ()
34#include <string>
35
36using namespace ns3;
37
39template <int N>
40class BenchHeader : public Header
41{
42 public:
51 bool IsOk() const;
52
57 static TypeId GetTypeId();
58 TypeId GetInstanceTypeId() const override;
59 void Print(std::ostream& os) const override;
60 uint32_t GetSerializedSize() const override;
61 void Serialize(Buffer::Iterator start) const override;
63
64 private:
69 static std::string GetTypeName();
70 bool m_ok;
71};
72
73template <int N>
75 : m_ok(false)
76{
77}
78
79template <int N>
80bool
82{
83 return m_ok;
84}
85
86template <int N>
87std::string
89{
90 std::ostringstream oss;
91 oss << "ns3::BenchHeader<" << N << ">";
92 return oss.str();
93}
94
95template <int N>
98{
99 static TypeId tid = TypeId(GetTypeName())
100 .SetParent<Header>()
101 .SetGroupName("Utils")
102 .HideFromDocumentation()
103 .AddConstructor<BenchHeader<N>>();
104 return tid;
105}
106
107template <int N>
108TypeId
110{
111 return GetTypeId();
112}
113
114template <int N>
115void
116BenchHeader<N>::Print(std::ostream& os) const
117{
118 NS_ASSERT(false);
119}
120
121template <int N>
124{
125 return N;
126}
127
128template <int N>
129void
131{
132 start.WriteU8(N, N);
133}
134
135template <int N>
138{
139 m_ok = true;
140 for (int i = 0; i < N; i++)
141 {
142 if (start.ReadU8() != N)
143 {
144 m_ok = false;
145 }
146 }
147 return N;
148}
149
151template <int N>
152class BenchTag : public Tag
153{
154 public:
159 static std::string GetName()
160 {
161 std::ostringstream oss;
162 oss << "anon::BenchTag<" << N << ">";
163 return oss.str();
164 }
165
171 {
172 static TypeId tid = TypeId(GetName())
173 .SetParent<Tag>()
174 .SetGroupName("Utils")
175 .HideFromDocumentation()
176 .AddConstructor<BenchTag<N>>();
177 return tid;
178 }
179
180 TypeId GetInstanceTypeId() const override
181 {
182 return GetTypeId();
183 }
184
186 {
187 return N;
188 }
189
190 void Serialize(TagBuffer buf) const override
191 {
192 for (uint32_t i = 0; i < N; ++i)
193 {
194 buf.WriteU8(N);
195 }
196 }
197
198 void Deserialize(TagBuffer buf) override
199 {
200 for (uint32_t i = 0; i < N; ++i)
201 {
202 buf.ReadU8();
203 }
204 }
205
206 void Print(std::ostream& os) const override
207 {
208 os << "N=" << N;
209 }
210
212 : Tag()
213 {
214 }
215};
216
217static void
219{
220 BenchHeader<25> ipv4;
221 BenchHeader<8> udp;
222 BenchTag<16> tag1;
223 BenchTag<17> tag2;
224
225 for (uint32_t i = 0; i < n; i++)
226 {
227 Ptr<Packet> p = Create<Packet>(2000);
228 p->AddPacketTag(tag1);
229 p->AddHeader(udp);
230 p->RemovePacketTag(tag1);
231 p->AddPacketTag(tag2);
232 p->AddHeader(ipv4);
233 Ptr<Packet> o = p->Copy();
234 o->RemoveHeader(ipv4);
235 p->RemovePacketTag(tag2);
236 o->RemoveHeader(udp);
237 }
238}
239
240static void
242{
243 BenchHeader<25> ipv4;
244 BenchHeader<8> udp;
245
246 // The original version of this program did not use BenchHeader::IsOK ()
247 // Below are two asserts that suggest how it can be used.
248 NS_ASSERT_MSG(ipv4.IsOk() == false, "IsOk() should be false before deserialization");
249 for (uint32_t i = 0; i < n; i++)
250 {
251 Ptr<Packet> p = Create<Packet>(2000);
252 p->AddHeader(udp);
253 p->AddHeader(ipv4);
254 Ptr<Packet> o = p->Copy();
255 o->RemoveHeader(ipv4);
256 o->RemoveHeader(udp);
257 }
258 NS_ASSERT_MSG(ipv4.IsOk() == true, "IsOk() should be true after deserialization");
259}
260
261static void
263{
264 BenchHeader<25> ipv4;
265 BenchHeader<8> udp;
266
267 for (uint32_t i = 0; i < n; i++)
268 {
269 Ptr<Packet> p = Create<Packet>(2000);
270 p->AddHeader(udp);
271 p->AddHeader(ipv4);
272 }
273}
274
275static void
277{
278 BenchHeader<8> udp;
279
280 p->RemoveHeader(udp);
281}
282
283static void
285{
286 BenchHeader<25> ipv4;
287 p->RemoveHeader(ipv4);
288 C2(p);
289}
290
291static void
293{
294 BenchHeader<25> ipv4;
295 BenchHeader<8> udp;
296
297 for (uint32_t i = 0; i < n; i++)
298 {
299 Ptr<Packet> p = Create<Packet>(2000);
300 p->AddHeader(udp);
301 p->AddHeader(ipv4);
302 C1(p);
303 }
304}
305
306static void
308{
309 BenchHeader<25> ipv4;
310 BenchHeader<8> udp;
311
312 for (uint32_t i = 0; i < n; i++)
313 {
314 Ptr<Packet> p = Create<Packet>(2000);
315 p->AddHeader(udp);
316 p->AddHeader(ipv4);
317
318 Ptr<Packet> frag0 = p->CreateFragment(0, 250);
319 Ptr<Packet> frag1 = p->CreateFragment(250, 250);
320 Ptr<Packet> frag2 = p->CreateFragment(500, 500);
321 Ptr<Packet> frag3 = p->CreateFragment(1000, 500);
322 Ptr<Packet> frag4 = p->CreateFragment(1500, 500);
323
324 /* Mix fragments in different order */
325 frag2->AddAtEnd(frag3);
326 frag4->AddAtEnd(frag1);
327 frag2->AddAtEnd(frag4);
328 frag0->AddAtEnd(frag2);
329
330 frag0->RemoveHeader(ipv4);
331 frag0->RemoveHeader(udp);
332 }
333}
334
335static void
337{
338 for (uint32_t i = 0; i < n; i++)
339 {
340 Ptr<Packet> p = Create<Packet>(2000);
341 for (uint32_t j = 0; j < 100; j++)
342 {
343 BenchTag<0> tag;
344 p->AddByteTag(tag);
345 }
346 Ptr<Packet> q = Create<Packet>(1000);
347
348 // This should trigger adjustment of all byte tags
349 q->AddAtEnd(p);
350 }
351}
352
353static uint64_t
355{
357 time.Start();
358 (*bench)(n);
359 uint64_t deltaMs = time.End();
360 return deltaMs;
361}
362
363static void
364runBench(void (*bench)(uint32_t), uint32_t n, uint32_t minIterations, const char* name)
365{
366 uint64_t minDelay = std::numeric_limits<uint64_t>::max();
367 for (uint32_t i = 0; i < minIterations; i++)
368 {
369 uint64_t delay = runBenchOneIteration(bench, n);
370 minDelay = std::min(minDelay, delay);
371 }
372 double ps = n;
373 ps *= 1000;
374 ps /= minDelay;
375 std::cout << ps << " packets/s"
376 << " (" << minDelay << " ms elapsed)\t" << name << std::endl;
377}
378
379int
380main(int argc, char* argv[])
381{
382 uint32_t n = 0;
383 uint32_t minIterations = 1;
384 bool enablePrinting = false;
385
386 CommandLine cmd(__FILE__);
387 cmd.Usage("Benchmark Packet class");
388 cmd.AddValue("n", "number of iterations", n);
389 cmd.AddValue("min-iterations",
390 "number of subiterations to minimize iteration time over",
391 minIterations);
392 cmd.AddValue("enable-printing", "enable packet printing", enablePrinting);
393 cmd.Parse(argc, argv);
394
395 if (n == 0)
396 {
397 std::cerr << "Error-- number of packets must be specified "
398 << "by command-line argument --n=(number of packets)" << std::endl;
399 exit(1);
400 }
401 std::cout << "Running bench-packets with n=" << n << std::endl;
402 std::cout << "All tests begin by adding UDP and IPv4 headers." << std::endl;
403
404 runBench(&benchA, n, minIterations, "Copy packet, remove headers");
405 runBench(&benchB, n, minIterations, "Just add headers");
406 runBench(&benchC, n, minIterations, "Remove by func call");
407 runBench(&benchD, n, minIterations, "Intermixed add/remove headers and tags");
408 runBench(&benchFragment, n, minIterations, "Fragmentation and concatenation");
409 runBench(&benchByteTags, n, minIterations, "Benchmark byte tags");
410
411 return 0;
412}
static void benchB(uint32_t n)
static void runBench(void(*bench)(uint32_t), uint32_t n, uint32_t minIterations, const char *name)
static uint64_t runBenchOneIteration(void(*bench)(uint32_t), uint32_t n)
static void benchC(uint32_t n)
static void benchD(uint32_t n)
static void benchFragment(uint32_t n)
static void benchByteTags(uint32_t n)
static void benchA(uint32_t n)
static void C1(Ptr< Packet > p)
static void C2(Ptr< Packet > p)
BenchHeader class used for benchmarking packet serialization/deserialization.
TypeId GetInstanceTypeId() const override
Get the most derived TypeId for this Object.
void Serialize(Buffer::Iterator start) const override
uint32_t Deserialize(Buffer::Iterator start) override
uint32_t GetSerializedSize() const override
static std::string GetTypeName()
Get type name function.
bool m_ok
variable to track whether deserialization succeeded
bool IsOk() const
Returns true if the header has been deserialized and the deserialization was correct.
static TypeId GetTypeId()
Register this type.
void Print(std::ostream &os) const override
BenchTag class used for benchmarking packet serialization/deserialization.
void Serialize(TagBuffer buf) const override
void Deserialize(TagBuffer buf) override
static TypeId GetTypeId()
Register this type.
uint32_t GetSerializedSize() const override
void Print(std::ostream &os) const override
TypeId GetInstanceTypeId() const override
Get the most derived TypeId for this Object.
static std::string GetName()
Get the bench tag name.
iterator in a Buffer instance
Definition: buffer.h:100
Parse command-line arguments.
Definition: command-line.h:232
Protocol header serialization and deserialization.
Definition: header.h:44
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:77
Measure elapsed wall clock time in milliseconds.
int64_t End()
Stop measuring the time since Start() was called.
void Start()
Start a measure.
read and write tag data
Definition: tag-buffer.h:52
TAG_BUFFER_INLINE void WriteU8(uint8_t v)
Definition: tag-buffer.h:172
TAG_BUFFER_INLINE uint8_t ReadU8()
Definition: tag-buffer.h:196
tag a set of bytes in a packet
Definition: tag.h:39
a unique identifier for an interface.
Definition: type-id.h:59
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:932
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
Definition: assert.h:66
#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:86
Every class exported by the ns3 library is enclosed in the ns3 namespace.
ns cmd
Definition: second.py:40