Skip to content

Instantly share code, notes, and snippets.

@pavel-odintsov
Last active February 20, 2022 21:04
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pavel-odintsov/22f9bc22aa0728e4b7e8327cc3438a49 to your computer and use it in GitHub Desktop.
Save pavel-odintsov/22f9bc22aa0728e4b7e8327cc3438a49 to your computer and use it in GitHub Desktop.
Patricia performance test for Medium
#include <arpa/inet.h>
#include <fstream>
#include <iostream>
#include <math.h>
#include <netinet/in.h>
#include <stdint.h>
#include <stdio.h>
#include <string>
#include <sys/socket.h>
#include <sys/time.h>
#include <time.h>
#include <unistd.h>
#include "nlohmann/json.hpp"
#include "fast_library.h"
#include "../libpatricia/patricia.h"
using json = nlohmann::json;
int main() {
patricia_tree_t* lookup_tree;
lookup_tree = New_Patricia(32);
std::string line;
std::ifstream myfile("isp_prefixes.txt");
if (!myfile.is_open()) {
std::cerr << "Could not open file with prefix list" << std::endl;
return 1;
}
std::cout << "Start subnet load to patricia" << std::endl;
while (getline(myfile, line)) {
make_and_lookup(lookup_tree, (char*)line.c_str());
}
std::cout << "Finished subnet load to patricia" << std::endl;
// Load example traffic
std::ifstream example_traffic("real_traffic.json");
if (!example_traffic.is_open()) {
std::cerr << "Could not open file with example traffic" << std::endl;
return 1;
}
std::vector<std::pair<uint32_t, uint32_t>> fragmented_vector_of_packets;
std::cout << "Start loading traffic into memory" << std::endl;
while (getline(example_traffic, line)) {
auto json_conf = json::parse(line, nullptr, false);
if (json_conf.is_discarded()) {
std::cerr << "Could not parse JSON: " << line << std::endl;
return 1;
}
// We test only IPv4 for now
if (json_conf["ip_version"].get<std::string>() != "ipv4") {
continue;
}
uint32_t src_ip = 0;
uint32_t dst_ip = 0;
bool source_res = convert_ip_as_string_to_uint_safe(json_conf["source_ip"].get<std::string>(), src_ip);
if (!source_res) {
std::cout << "Cannot parse src ip" << std::endl;
continue;
}
bool destionation_res = convert_ip_as_string_to_uint_safe(json_conf["destination_ip"].get<std::string>(), dst_ip);
if (!destionation_res) {
std::cout << "Cannot parse dst ip" << std::endl;
continue;
}
fragmented_vector_of_packets.push_back(std::make_pair(src_ip, dst_ip));
}
std::cout << "Loaded traffic into memory" << std::endl;
std::cout << "Defragment memory for input packet set" << std::endl;
// Copy traffic into single continious memory regiuon to avoid issues performance issues due to memory frragmentation
std::vector<std::pair<uint32_t, uint32_t>> vector_of_packets;
vector_of_packets.reserve(fragmented_vector_of_packets.size());
for (const auto& pair: fragmented_vector_of_packets) {
vector_of_packets.push_back(pair);
}
fragmented_vector_of_packets.clear();
std::cout << "Defragmentation done" << std::endl;
std::cout << "I have " << vector_of_packets.size() << " real packets for test" << std::endl;
std::cout << "Start tests" << std::endl;
// Process vector_of_packets
prefix_t prefix_for_check_adreess;
prefix_for_check_adreess.family = AF_INET;
prefix_for_check_adreess.bitlen = 32;
// prefix_for_check_adreess.add.sin.s_addr = 123123123;
struct timespec start_time;
clock_gettime(CLOCK_REALTIME, &start_time);
uint64_t number_of_reruns = 100000;
// I do not multiple by two here becasue we assume that interation involves two lookups all the time
unsigned long total_ops = number_of_reruns * vector_of_packets.size();
uint64_t match_source = 0;
uint64_t match_destionation = 0;
for (int j = 0; j < number_of_reruns; j++) {
for (const auto& pair: vector_of_packets) {
prefix_for_check_adreess.add.sin.s_addr = pair.first;
patricia_node_t* found_patrica_node = patricia_search_best2(lookup_tree, &prefix_for_check_adreess, 1);
if (found_patrica_node != NULL) {
match_source++;
}
// Repeat for another IP
prefix_for_check_adreess.add.sin.s_addr = pair.second;
found_patrica_node = patricia_search_best2(lookup_tree, &prefix_for_check_adreess, 1);
if (found_patrica_node != NULL) {
match_destionation++;
}
}
}
struct timespec finish_time;
clock_gettime(CLOCK_REALTIME, &finish_time);
std::cout << "match_source: " << match_source << " match_destionation: " << match_destionation << std::endl;
unsigned long used_seconds = finish_time.tv_sec - start_time.tv_sec;
unsigned long used_nanoseconds = finish_time.tv_nsec - start_time.tv_nsec;
unsigned long total_used_nanoseconds = used_seconds * 1000000000 + used_nanoseconds;
float megaops_per_second = (float)total_ops / ((float)total_used_nanoseconds / (float)1000000000) / 1000000;
printf("Total time is %d seconds total ops: %d\nMillion of ops per second: "
"%.1f\n",
used_seconds, total_ops, megaops_per_second);
Destroy_Patricia(lookup_tree, [](void* ptr) {});
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment