TeaSpeakLibrary/test/ip_router.cpp
2020-03-09 18:29:43 +01:00

173 lines
5.0 KiB
C++

#include <assert.h>
#include <iostream>
#include <src/misc/net.h>
#include <netinet/in.h>
#include "src/misc/ip_router.h"
using namespace ts::network;
inline sockaddr_storage address(const std::string& address) {
sockaddr_storage result{};
memset(&result, 0, sizeof(result));
net::resolve_address(address, result);
return result;
}
inline void resolve(ip_router& router, const std::string& address_str) {
std::cout << address_str << " -> " << router.resolve(address(address_str)) << std::endl;
}
/*
IPv6 & 15000 iterations
0% misses:
Time per resolve: 608ns
50% misses:
Time per resolve: 448ns
100% misses:
Time per resolve: 30ns
IPv6 & 15000 iterations & shared mutex
0% misses:
Time per resolve: 848ns
50% misses:
Time per resolve: 602ns
100% misses:
Time per resolve: 39ns
IPv6 & 15000 iterations & spin lock
0% misses:
Time per resolve: 743ns
50% misses:
Time per resolve: 510ns
100% misses:
Time per resolve: 29ns
New system:
0% misses:
Time per resolve: 149ns
Used memory: 67.155kb
50% misses:
Time per resolve: 71ns
Used memory: 32.501kb
100% misses:
Time per resolve: 14ns
Used memory: 4kb
*/
inline void benchmark_resolve() {
const auto iterations = 500;
std::vector<sockaddr_storage> addresses{};
/* generate addresses */
{
const auto rnd = []{
return (uint32_t) ((uint8_t) ::rand());
};
for(int i = 0; i < iterations; i++) {
auto& address = addresses.emplace_back();
address.ss_family = AF_INET;
auto address4 = (sockaddr_in*) &address;
address4->sin_addr.s_addr = (rnd() << 24U) | (rnd() << 16U) | (rnd() << 8U) | (rnd() << 0U);
}
#if 0
for(int i = 0; i < iterations; i++) {
auto& address = addresses.emplace_back();
address.ss_family = AF_INET6;
auto address6 = (sockaddr_in6*) &address;
for(auto& part : address6->sin6_addr.__in6_u.__u6_addr8)
part = rand();
}
#endif
}
for(auto missPercentage : {0, 50, 100}) {
std::cout << missPercentage << "% misses:\n";
ip_router rounter{};
for(auto& address : addresses) {
if((::rand() % 100) < missPercentage) continue;
rounter.register_route(address, &address, nullptr);
}
/* resolve */
{
auto begin = std::chrono::system_clock::now();
size_t index{0};
for(auto& address : addresses) {
index++;
auto result = rounter.resolve(address);
(void) result;
//if(missPercentage == 0 && memcmp(result, &address, sizeof(address)) != 0)
// __asm__("nop");
}
auto end = std::chrono::system_clock::now();
std::cout << "Total time: " << std::chrono::ceil<std::chrono::microseconds>(end - begin).count() << "us\n";
std::cout << "Time per resolve: " << std::chrono::ceil<std::chrono::nanoseconds>(end - begin).count() / iterations << "ns\n";
std::cout << "Used memory: " << rounter.used_memory() / 1024 << "kb" << std::endl;
__asm__("nop");
if(missPercentage == 0)
;//std::cout << "Tree:\n" << rounter.print_as_string() << "\n";
}
}
/* resolve */
{
std::cout << "List iterate:\n";
auto begin = std::chrono::system_clock::now();
for(auto& address : addresses) {
for(auto& addressB : addresses)
if(memcmp(&address, &addressB, sizeof(sockaddr_storage)) == 0)
break;
}
auto end = std::chrono::system_clock::now();
std::cout << "Total time: " << std::chrono::ceil<std::chrono::microseconds>(end - begin).count() << "us\n";
std::cout << "Time per resolve: " << std::chrono::ceil<std::chrono::nanoseconds>(end - begin).count() / iterations << "ns\n";
}
}
int main() {
#if 0
ip_router rounter{};
assert(rounter.validate_tree());
resolve(rounter, "127.0.0.1");
rounter.register_route(address("127.0.0.1"), (void*) 0x127001);
assert(rounter.validate_tree());
resolve(rounter, "127.0.0.1");
rounter.register_route(address("127.0.0.2"), (void*) 0x127002);
assert(rounter.validate_tree());
resolve(rounter, "127.0.0.2");
resolve(rounter, "127.0.1.2");
rounter.register_route(address("127.0.1.2"), (void*) 0x127012);
resolve(rounter, "127.0.0.2");
resolve(rounter, "127.0.1.2");
std::cout << "Tree:\n" << rounter.print_as_string() << "\n";
rounter.reset_route(address("127.0.0.1"));
assert(rounter.validate_tree());
resolve(rounter, "127.0.0.1");
resolve(rounter, "127.0.0.2");
rounter.reset_route(address("127.0.0.2"));
assert(rounter.validate_tree());
resolve(rounter, "127.0.0.1");
resolve(rounter, "127.0.0.2");
#endif
benchmark_resolve();
return 0;
}