-
Notifications
You must be signed in to change notification settings - Fork 683
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add a benchmark which uses Google benchmark library (#1392)
* Add attestation steps for packaging * tab to spaces * update permissions * Update README for verify procedure * fix * version to commit hash * Use google benchmark * add stats * update comment * change default opt * add workflow * test package install * forgot to build :) * fix path * fix path * fix path again * pre-commit fixes * Fix cmake format + disable pull requests * disable verbose * add dev for testing * add ignore files * upload as artifact for test * upload results as artifact to generate charts manually * change action version format * update * remove ubuntu 18.04 * move permissions * should be package dir * remove wildcard * bump version str * fix format issues * move benchmark * compile success * minor fixes * remove unnecessary changes * not related * test benchmark workflow is buildable * Add PRs temporarily * fix errors * fix * no need matrix * use bencher * remove bencher * minor update * Add write and crafting benchmarks * update function names * add info to benchmarks * update path * update python * format fix * fix typos * simplify * use pps * use FetchContent to get benchmark * Rename benchmark in example because same name with lib * format cmake * simplify parsedPacket process * move benchmarks to examples * set cross-compiling * Revert "set cross-compiling" This reverts commit 66b3e14. * change readme and enable benchmark for only linux * revert unnecessary change * improve readme * fix for comments * table header * pre-commit fix * remove PCAPPP_USE_GOOGLEBENCHMARK * test cross-compile macos * use additional flag for macos13 * add same flag to tutorial build * disable google bench lib install * add comment to cmake * test macos from CI * auto detect C++14 * remove additional flags * fetchcontent_makeavailable requires 3.14 * fix macos arch difference * add warning message for C++14 * fix logic --------- Co-authored-by: seladb <[email protected]>
- Loading branch information
Showing
5 changed files
with
294 additions
and
8 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) | ||
{ | ||
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; | ||
} |