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 * SPDX-License-Identifier: GPL-2.0-only
5 *
6 * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
7 */
8
9// This program can be used to benchmark packet serialization/deserialization
10// operations using Headers and Tags, for various numbers of packets 'n'
11// Sample usage: ./ns3 run 'bench-packets --n=10000'
12
13#include "ns3/command-line.h"
14#include "ns3/packet-metadata.h"
15#include "ns3/packet.h"
16#include "ns3/system-wall-clock-ms.h"
17
18#include <algorithm>
19#include <iostream>
20#include <limits>
21#include <sstream>
22#include <stdlib.h> // for exit ()
23#include <string>
24
25using namespace ns3;
26
27/// BenchHeader class used for benchmarking packet serialization/deserialization
28template <int N>
29class BenchHeader : public Header
30{
31 public:
33 /**
34 * Returns true if the header has been deserialized and the
35 * deserialization was correct. If Deserialize() has not yet been
36 * called on the header, will return false.
37 *
38 * \returns true if success, false if failed or if deserialization not tried
39 */
40 bool IsOk() const;
41
42 /**
43 * Register this type.
44 * \return The TypeId.
45 */
46 static TypeId GetTypeId();
47 TypeId GetInstanceTypeId() const override;
48 void Print(std::ostream& os) const override;
49 uint32_t GetSerializedSize() const override;
50 void Serialize(Buffer::Iterator start) const override;
52
53 private:
54 /**
55 * Get type name function
56 * \returns the type name string
57 */
58 static std::string GetTypeName();
59 bool m_ok; ///< variable to track whether deserialization succeeded
60};
61
62template <int N>
64 : m_ok(false)
65{
66}
67
68template <int N>
69bool
71{
72 return m_ok;
73}
74
75template <int N>
76std::string
78{
79 std::ostringstream oss;
80 oss << "ns3::BenchHeader<" << N << ">";
81 return oss.str();
82}
83
84template <int N>
87{
88 static TypeId tid = TypeId(GetTypeName())
90 .SetGroupName("Utils")
91 .HideFromDocumentation()
92 .AddConstructor<BenchHeader<N>>();
93 return tid;
94}
95
96template <int N>
99{
100 return GetTypeId();
101}
102
103template <int N>
104void
105BenchHeader<N>::Print(std::ostream& os) const
106{
107 NS_ASSERT(false);
108}
109
110template <int N>
113{
114 return N;
115}
116
117template <int N>
118void
120{
121 start.WriteU8(N, N);
122}
123
124template <int N>
127{
128 m_ok = true;
129 for (int i = 0; i < N; i++)
130 {
131 if (start.ReadU8() != N)
132 {
133 m_ok = false;
134 }
135 }
136 return N;
137}
138
139/// BenchTag class used for benchmarking packet serialization/deserialization
140template <int N>
141class BenchTag : public Tag
142{
143 public:
144 /**
145 * Get the bench tag name.
146 * \return the name.
147 */
148 static std::string GetName()
149 {
150 std::ostringstream oss;
151 oss << "anon::BenchTag<" << N << ">";
152 return oss.str();
153 }
154
155 /**
156 * Register this type.
157 * \return The TypeId.
158 */
160 {
161 static TypeId tid = TypeId(GetName())
162 .SetParent<Tag>()
163 .SetGroupName("Utils")
164 .HideFromDocumentation()
165 .AddConstructor<BenchTag<N>>();
166 return tid;
167 }
168
169 TypeId GetInstanceTypeId() const override
170 {
171 return GetTypeId();
172 }
173
175 {
176 return N;
177 }
178
179 void Serialize(TagBuffer buf) const override
180 {
181 for (uint32_t i = 0; i < N; ++i)
182 {
183 buf.WriteU8(N);
184 }
185 }
186
187 void Deserialize(TagBuffer buf) override
188 {
189 for (uint32_t i = 0; i < N; ++i)
190 {
191 buf.ReadU8();
192 }
193 }
194
195 void Print(std::ostream& os) const override
196 {
197 os << "N=" << N;
198 }
199
201 : Tag()
202 {
203 }
204};
205
206static void
208{
209 BenchHeader<25> ipv4;
210 BenchHeader<8> udp;
211 BenchTag<16> tag1;
212 BenchTag<17> tag2;
213
214 for (uint32_t i = 0; i < n; i++)
215 {
216 Ptr<Packet> p = Create<Packet>(2000);
217 p->AddPacketTag(tag1);
218 p->AddHeader(udp);
219 p->RemovePacketTag(tag1);
220 p->AddPacketTag(tag2);
221 p->AddHeader(ipv4);
222 Ptr<Packet> o = p->Copy();
223 o->RemoveHeader(ipv4);
224 p->RemovePacketTag(tag2);
225 o->RemoveHeader(udp);
226 }
227}
228
229static void
231{
232 BenchHeader<25> ipv4;
233 BenchHeader<8> udp;
234
235 // The original version of this program did not use BenchHeader::IsOK ()
236 // Below are two asserts that suggest how it can be used.
237 NS_ASSERT_MSG(ipv4.IsOk() == false, "IsOk() should be false before deserialization");
238 for (uint32_t i = 0; i < n; i++)
239 {
240 Ptr<Packet> p = Create<Packet>(2000);
241 p->AddHeader(udp);
242 p->AddHeader(ipv4);
243 Ptr<Packet> o = p->Copy();
244 o->RemoveHeader(ipv4);
245 o->RemoveHeader(udp);
246 }
247 NS_ASSERT_MSG(ipv4.IsOk() == true, "IsOk() should be true after deserialization");
248}
249
250static void
252{
253 BenchHeader<25> ipv4;
254 BenchHeader<8> udp;
255
256 for (uint32_t i = 0; i < n; i++)
257 {
258 Ptr<Packet> p = Create<Packet>(2000);
259 p->AddHeader(udp);
260 p->AddHeader(ipv4);
261 }
262}
263
264static void
266{
267 BenchHeader<8> udp;
268
269 p->RemoveHeader(udp);
270}
271
272static void
274{
275 BenchHeader<25> ipv4;
276 p->RemoveHeader(ipv4);
277 C2(p);
278}
279
280static void
282{
283 BenchHeader<25> ipv4;
284 BenchHeader<8> udp;
285
286 for (uint32_t i = 0; i < n; i++)
287 {
288 Ptr<Packet> p = Create<Packet>(2000);
289 p->AddHeader(udp);
290 p->AddHeader(ipv4);
291 C1(p);
292 }
293}
294
295static void
297{
298 BenchHeader<25> ipv4;
299 BenchHeader<8> udp;
300
301 for (uint32_t i = 0; i < n; i++)
302 {
303 Ptr<Packet> p = Create<Packet>(2000);
304 p->AddHeader(udp);
305 p->AddHeader(ipv4);
306
307 Ptr<Packet> frag0 = p->CreateFragment(0, 250);
308 Ptr<Packet> frag1 = p->CreateFragment(250, 250);
309 Ptr<Packet> frag2 = p->CreateFragment(500, 500);
310 Ptr<Packet> frag3 = p->CreateFragment(1000, 500);
311 Ptr<Packet> frag4 = p->CreateFragment(1500, 500);
312
313 /* Mix fragments in different order */
314 frag2->AddAtEnd(frag3);
315 frag4->AddAtEnd(frag1);
316 frag2->AddAtEnd(frag4);
317 frag0->AddAtEnd(frag2);
318
319 frag0->RemoveHeader(ipv4);
320 frag0->RemoveHeader(udp);
321 }
322}
323
324static void
326{
327 for (uint32_t i = 0; i < n; i++)
328 {
329 Ptr<Packet> p = Create<Packet>(2000);
330 for (uint32_t j = 0; j < 100; j++)
331 {
332 BenchTag<0> tag;
333 p->AddByteTag(tag);
334 }
335 Ptr<Packet> q = Create<Packet>(1000);
336
337 // This should trigger adjustment of all byte tags
338 q->AddAtEnd(p);
339 }
340}
341
342static uint64_t
344{
346 time.Start();
347 (*bench)(n);
348 uint64_t deltaMs = time.End();
349 return deltaMs;
350}
351
352static void
353runBench(void (*bench)(uint32_t), uint32_t n, uint32_t minIterations, const char* name)
354{
355 uint64_t minDelay = std::numeric_limits<uint64_t>::max();
356 for (uint32_t i = 0; i < minIterations; i++)
357 {
358 uint64_t delay = runBenchOneIteration(bench, n);
359 minDelay = std::min(minDelay, delay);
360 }
361 double ps = n;
362 ps *= 1000;
363 ps /= minDelay;
364 std::cout << ps << " packets/s"
365 << " (" << minDelay << " ms elapsed)\t" << name << std::endl;
366}
367
368int
369main(int argc, char* argv[])
370{
371 uint32_t n = 0;
372 uint32_t minIterations = 1;
373 bool enablePrinting = false;
374
375 CommandLine cmd(__FILE__);
376 cmd.Usage("Benchmark Packet class");
377 cmd.AddValue("n", "number of iterations", n);
378 cmd.AddValue("min-iterations",
379 "number of subiterations to minimize iteration time over",
380 minIterations);
381 cmd.AddValue("enable-printing", "enable packet printing", enablePrinting);
382 cmd.Parse(argc, argv);
383
384 if (n == 0)
385 {
386 std::cerr << "Error-- number of packets must be specified "
387 << "by command-line argument --n=(number of packets)" << std::endl;
388 exit(1);
389 }
390 std::cout << "Running bench-packets with n=" << n << std::endl;
391 std::cout << "All tests begin by adding UDP and IPv4 headers." << std::endl;
392
393 runBench(&benchA, n, minIterations, "Copy packet, remove headers");
394 runBench(&benchB, n, minIterations, "Just add headers");
395 runBench(&benchC, n, minIterations, "Remove by func call");
396 runBench(&benchD, n, minIterations, "Intermixed add/remove headers and tags");
397 runBench(&benchFragment, n, minIterations, "Fragmentation and concatenation");
398 runBench(&benchByteTags, n, minIterations, "Benchmark byte tags");
399
400 return 0;
401}
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:89
Parse command-line arguments.
Protocol header serialization and deserialization.
Definition header.h:33
Smart pointer class similar to boost::intrusive_ptr.
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:41
TAG_BUFFER_INLINE void WriteU8(uint8_t v)
Definition tag-buffer.h:161
TAG_BUFFER_INLINE uint8_t ReadU8()
Definition tag-buffer.h:185
tag a set of bytes in a packet
Definition tag.h:28
a unique identifier for an interface.
Definition type-id.h:48
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition type-id.cc:1001
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
Definition assert.h:55
#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:75
Ptr< T > Create(Ts &&... args)
Create class instances by constructors with varying numbers of arguments and return them by Ptr.
Definition ptr.h:436
Every class exported by the ns3 library is enclosed in the ns3 namespace.