-
Notifications
You must be signed in to change notification settings - Fork 683
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add a benchmark which uses Google benchmark library #1392
Changes from all commits
3eefad0
cc997aa
8235841
3fd4e01
202fb59
ba8be94
566566d
fe7d42d
bcd9d70
943f04d
5d346a5
e770341
345b5e7
8ed27cf
16fea77
82a8d93
b03aabd
50e76bb
0b56c68
ad48e8a
f0aab9d
9520bb0
4be134f
88f9f4a
96e9c5d
ea31445
dba91ea
62d8105
dda4c8f
ebf5d75
bb4b18d
d8f505b
746a174
44d309d
bb959b2
842680d
590be53
10169fa
17d5e8e
7bb2070
0642949
d76289a
4657572
d8db674
802e4f7
3564c8b
227a661
b6575c9
21e85d9
1022065
915817d
2881040
4b0c896
00997b6
7795cfc
7107fd6
ea982b7
caf6c64
72f6bd2
b6d7e98
5e8e056
27b4619
95b6562
d6e90c0
f9e4cfb
b9aad7d
90faf97
66b3e14
1588009
a8a2a46
ed12ae4
80152bf
6b861d7
58701ed
557839a
7ee9f25
1ecf4d6
bc5be8a
bb0e73d
9dd6134
f5d1a8b
de4ae9c
b1f00ab
7774cb6
10f40c2
419c63e
a6a9cb1
fe12995
9fc6e6e
bc4ab17
948d1cf
602ddd9
800f287
e8efae5
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -23,6 +23,7 @@ | |
*.pcapng.zst | ||
*.pcapng.zstd | ||
*.cap | ||
*.snoop | ||
|
||
#Bin and Obj directories | ||
**/Bin | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
cmake_minimum_required(VERSION 3.12) | ||
cmake_minimum_required(VERSION 3.14) | ||
|
||
project(PcapPlusPlusExamples) | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,12 +1,50 @@ | ||
add_executable(benchmark benchmark.cpp) | ||
add_executable(BenchmarkExample benchmark.cpp) | ||
|
||
target_link_libraries(benchmark PUBLIC PcapPlusPlus::Pcap++) | ||
target_link_libraries(BenchmarkExample PUBLIC PcapPlusPlus::Pcap++) | ||
|
||
set_target_properties(BenchmarkExample PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${PCAPPP_BINARY_EXAMPLES_DIR}") | ||
|
||
if("cxx_std_14" IN_LIST CMAKE_CXX_COMPILE_FEATURES) | ||
if( | ||
(CMAKE_HOST_SYSTEM_PROCESSOR STREQUAL CMAKE_SYSTEM_PROCESSOR) | ||
AND (NOT CMAKE_OSX_ARCHITECTURES OR (CMAKE_HOST_SYSTEM_PROCESSOR STREQUAL CMAKE_OSX_ARCHITECTURES)) | ||
) | ||
include(FetchContent) | ||
|
||
# Fetch Google Benchmark | ||
fetchcontent_declare( | ||
benchmark | ||
GIT_REPOSITORY https://github.com/google/benchmark.git | ||
GIT_TAG v1.9.0) | ||
|
||
# Disable testing and installation for Google Benchmark | ||
set(BENCHMARK_ENABLE_TESTING OFF) | ||
set(BENCHMARK_ENABLE_INSTALL OFF) | ||
fetchcontent_makeavailable(benchmark) | ||
|
||
add_executable(BenchmarkExampleGoogle benchmark-google.cpp) | ||
|
||
target_link_libraries(BenchmarkExampleGoogle PUBLIC PcapPlusPlus::Pcap++ benchmark::benchmark) | ||
|
||
set_target_properties(BenchmarkExampleGoogle PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${PCAPPP_BINARY_EXAMPLES_DIR}") | ||
else() | ||
message(WARNING "Google Benchmark backend is not supported for cross-compilation") | ||
endif() | ||
else() | ||
message(WARNING "Google Benchmark backend requires C++14 support") | ||
endif() | ||
|
||
set_target_properties(benchmark PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${PCAPPP_BINARY_EXAMPLES_DIR}") | ||
|
||
if(PCAPPP_INSTALL) | ||
install( | ||
TARGETS benchmark | ||
TARGETS BenchmarkExample | ||
EXPORT PcapPlusPlusTargets | ||
RUNTIME DESTINATION ${PCAPPP_INSTALL_BINDIR}) | ||
|
||
if(TARGET BenchmarkExampleGoogle) | ||
install( | ||
TARGETS BenchmarkExampleGoogle | ||
EXPORT PcapPlusPlusTargets | ||
RUNTIME DESTINATION ${PCAPPP_INSTALL_BINDIR}) | ||
endif() | ||
endif() |
seladb marked this conversation as resolved.
Show resolved
Hide resolved
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,8 +1,19 @@ | ||
PcapPlusPlus Benchmark | ||
====================== | ||
|
||
This is a benchmark application used for measuring PcapPlusPlus performance. It is based on Matias Fontanini's packet-capture-benchmarks project (https://github.com/mfontanini/packet-capture-benchmarks). | ||
This folder contains benchmark applications for measuring the performance of PcapPlusPlus. Currently, there are two benchmark applications. | ||
|
||
See this page for more details: https://pcapplusplus.github.io/docs/benchmark | ||
## Compare with other libraries | ||
|
||
This application currently compiles on Linux only (where benchmark was running on) | ||
A benchmark application used for measuring PcapPlusPlus performance can be found in `benchmark.cpp`. It is based on Matias Fontanini's packet-capture-benchmarks project (https://github.com/mfontanini/packet-capture-benchmarks) and allows us to compare PcapPlusPlus with other packet libraries. See this page for more details and result comparisons: https://pcapplusplus.github.io/docs/benchmark | ||
|
||
## Directly benchmark PcapPlusPlus | ||
|
||
Another application integrates with the Google Benchmark library and can be found in `benchmark-google.cpp`. This application currently consists of four different benchmarks, and each benchmark can be influenced by various factors. These benchmarks aim to utilize different influence factors to provide accurate results for different scenarios. You can check the table below for more information. For performance-critical applications using PcapPlusPlus, it is recommended to run benchmarks in your specific environment for more accurate results. Using larger pcap files and those with diverse protocols and sessions can provide better insights into PcapPlusPlus performance in your setup. | ||
|
||
| Benchmark | Operation | Influencing factors | | ||
|:-----------------:|:-------------:|:--------------------:| | ||
| BM_PcapFileRead | Read | CPU + Disk (Read) | | ||
| BM_PcapFileWrite | Write | CPU + Disk (Write) | | ||
| BM_PacketParsing | Read + Parse | CPU + Disk (Read) | | ||
| BM_PacketCrafting | Craft | CPU | |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,236 @@ | ||
#include <Packet.h> | ||
#include <PcapFileDevice.h> | ||
#include <PcapPlusPlusVersion.h> | ||
|
||
#include <EthLayer.h> | ||
#include <IPv4Layer.h> | ||
#include <IPv6Layer.h> | ||
#include <TcpLayer.h> | ||
#include <UdpLayer.h> | ||
|
||
#include <benchmark/benchmark.h> | ||
|
||
#include <iostream> | ||
|
||
static std::string pcapFileName = ""; | ||
|
||
static void BM_PcapFileRead(benchmark::State& state) | ||
{ | ||
// Open the pcap file for reading | ||
pcpp::PcapFileReaderDevice reader(pcapFileName); | ||
if (!reader.open()) | ||
{ | ||
state.SkipWithError("Cannot open pcap file for reading"); | ||
return; | ||
} | ||
|
||
size_t totalBytes = 0; | ||
size_t totalPackets = 0; | ||
pcpp::RawPacket rawPacket; | ||
for (auto _ : state) | ||
{ | ||
if (!reader.getNextPacket(rawPacket)) | ||
{ | ||
// If the rawPacket is empty there should be an error | ||
if (totalBytes == 0) | ||
{ | ||
state.SkipWithError("Cannot read packet"); | ||
return; | ||
} | ||
|
||
// Rewind the file if it reached the end | ||
state.PauseTiming(); | ||
reader.close(); | ||
reader.open(); | ||
state.ResumeTiming(); | ||
continue; | ||
} | ||
|
||
++totalPackets; | ||
totalBytes += rawPacket.getRawDataLen(); | ||
} | ||
|
||
state.SetBytesProcessed(totalBytes); | ||
state.SetItemsProcessed(totalPackets); | ||
} | ||
BENCHMARK(BM_PcapFileRead); | ||
|
||
static void BM_PcapFileWrite(benchmark::State& state) | ||
{ | ||
// Open the pcap file for writing | ||
pcpp::PcapFileWriterDevice writer("benchmark-output.pcap"); | ||
if (!writer.open()) | ||
{ | ||
state.SkipWithError("Cannot open pcap file for writing"); | ||
return; | ||
} | ||
|
||
pcpp::Packet packet; | ||
pcpp::EthLayer ethLayer(pcpp::MacAddress("00:00:00:00:00:00"), pcpp::MacAddress("00:00:00:00:00:00")); | ||
pcpp::IPv4Layer ip4Layer(pcpp::IPv4Address("192.168.0.1"), pcpp::IPv4Address("192.168.0.2")); | ||
pcpp::TcpLayer tcpLayer(12345, 80); | ||
|
||
packet.addLayer(ðLayer); | ||
packet.addLayer(&ip4Layer); | ||
packet.addLayer(&tcpLayer); | ||
packet.computeCalculateFields(); | ||
|
||
size_t totalBytes = 0; | ||
size_t totalPackets = 0; | ||
for (auto _ : state) | ||
{ | ||
// Write packet to file | ||
writer.writePacket(*(packet.getRawPacket())); | ||
|
||
// Count total bytes and packets | ||
++totalPackets; | ||
totalBytes += packet.getRawPacket()->getRawDataLen(); | ||
} | ||
|
||
// Set statistics to the benchmark state | ||
state.SetBytesProcessed(totalBytes); | ||
state.SetItemsProcessed(totalPackets); | ||
} | ||
BENCHMARK(BM_PcapFileWrite); | ||
|
||
static void BM_PacketParsing(benchmark::State& state) | ||
{ | ||
// Open the pcap file for reading | ||
size_t totalBytes = 0; | ||
size_t totalPackets = 0; | ||
pcpp::PcapFileReaderDevice reader(pcapFileName); | ||
if (!reader.open()) | ||
{ | ||
state.SkipWithError("Cannot open pcap file for reading"); | ||
return; | ||
} | ||
|
||
pcpp::RawPacket rawPacket; | ||
for (auto _ : state) | ||
{ | ||
if (!reader.getNextPacket(rawPacket)) | ||
{ | ||
// If the rawPacket is empty there should be an error | ||
if (totalBytes == 0) | ||
{ | ||
state.SkipWithError("Cannot read packet"); | ||
return; | ||
} | ||
|
||
// Rewind the file if it reached the end | ||
state.PauseTiming(); | ||
reader.close(); | ||
reader.open(); | ||
state.ResumeTiming(); | ||
continue; | ||
} | ||
|
||
// Parse packet | ||
pcpp::Packet parsedPacket(&rawPacket); | ||
|
||
// Use parsedPacket to prevent compiler optimizations | ||
assert(parsedPacket.getFirstLayer()); | ||
|
||
// Count total bytes and packets | ||
++totalPackets; | ||
totalBytes += rawPacket.getRawDataLen(); | ||
} | ||
|
||
// Set statistics to the benchmark state | ||
state.SetBytesProcessed(totalBytes); | ||
state.SetItemsProcessed(totalPackets); | ||
} | ||
BENCHMARK(BM_PacketParsing); | ||
|
||
static void BM_PacketCrafting(benchmark::State& state) | ||
{ | ||
size_t totalBytes = 0; | ||
size_t totalPackets = 0; | ||
|
||
for (auto _ : state) | ||
{ | ||
uint8_t randNum = static_cast<uint8_t>(rand() % 256); | ||
|
||
pcpp::Packet packet; | ||
|
||
// Generate random MAC addresses | ||
pcpp::MacAddress srcMac(randNum, randNum, randNum, randNum, randNum, randNum); | ||
pcpp::MacAddress dstMac(randNum, randNum, randNum, randNum, randNum, randNum); | ||
packet.addLayer(new pcpp::EthLayer(srcMac, dstMac), true); | ||
|
||
// Randomly choose between IPv4 and IPv6 | ||
if (randNum % 2) | ||
{ | ||
packet.addLayer(new pcpp::IPv4Layer(randNum, randNum), true); | ||
} | ||
else | ||
{ | ||
std::array<uint8_t, 16> srcIP = { randNum, randNum, randNum, randNum, randNum, randNum, randNum, randNum, | ||
randNum, randNum, randNum, randNum, randNum, randNum, randNum, randNum }; | ||
std::array<uint8_t, 16> dstIP = { randNum, randNum, randNum, randNum, randNum, randNum, randNum, randNum, | ||
randNum, randNum, randNum, randNum, randNum, randNum, randNum, randNum }; | ||
|
||
packet.addLayer(new pcpp::IPv6Layer(srcIP, dstIP), true); | ||
} | ||
|
||
// Randomly choose between TCP and UDP | ||
if (randNum % 2) | ||
{ | ||
packet.addLayer(new pcpp::TcpLayer(randNum % 65536, randNum % 65536), true); | ||
} | ||
else | ||
{ | ||
packet.addLayer(new pcpp::UdpLayer(randNum % 65536, randNum % 65536), true); | ||
} | ||
|
||
// Calculate all fields to update the packet | ||
packet.computeCalculateFields(); | ||
|
||
// Count total bytes and packets | ||
++totalPackets; | ||
totalBytes += packet.getRawPacket()->getRawDataLen(); | ||
} | ||
|
||
// Set statistics to the benchmark state | ||
state.SetBytesProcessed(totalBytes); | ||
state.SetItemsProcessed(totalPackets); | ||
} | ||
BENCHMARK(BM_PacketCrafting); | ||
|
||
int main(int argc, char** argv) | ||
{ | ||
// Initialize the benchmark | ||
benchmark::Initialize(&argc, argv); | ||
|
||
// Parse command line arguments to find the pcap file name | ||
for (int idx = 1; idx < argc; ++idx) | ||
{ | ||
if (strcmp(argv[idx], "--pcap-file") == 0) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Since
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @seladb The problem is arguments are also used by google benchmark. It supports some flags as default, for example There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oh ok, so we can keep it 👍 |
||
{ | ||
if (idx == argc - 1) | ||
{ | ||
std::cerr << "Please provide a pcap file name after --pcap-file" << std::endl; | ||
return 1; | ||
} | ||
|
||
pcapFileName = argv[idx + 1]; | ||
break; | ||
} | ||
} | ||
|
||
if (pcapFileName.empty()) | ||
{ | ||
std::cerr << "Please provide a pcap file name using --pcap-file" << std::endl; | ||
return 1; | ||
} | ||
|
||
benchmark::AddCustomContext("PcapPlusPlus version", pcpp::getPcapPlusPlusVersionFull()); | ||
benchmark::AddCustomContext("Build info", pcpp::getBuildDateTime()); | ||
benchmark::AddCustomContext("Git info", pcpp::getGitInfo()); | ||
benchmark::AddCustomContext("Pcap file", pcapFileName); | ||
|
||
// Run the benchmarks | ||
benchmark::RunSpecifiedBenchmarks(); | ||
|
||
return 0; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fetchcontent_makeavailable
added in 3.14