diff --git a/libraries/networking/src/HifiSockAddr.h b/libraries/networking/src/HifiSockAddr.h index 25f7ad2194..e6f018413f 100644 --- a/libraries/networking/src/HifiSockAddr.h +++ b/libraries/networking/src/HifiSockAddr.h @@ -70,10 +70,24 @@ uint qHash(const HifiSockAddr& key, uint seed); template <> struct std::hash { + // NOTE: this hashing specifically ignores IPv6 addresses - if we begin to support those we will need + // to conditionally hash the bytes that represent an IPv6 address std::size_t operator()(const HifiSockAddr& sockAddr) const { // use XOR of implemented std::hash templates for new hash - return std::hash()(sockAddr.getAddress().toString().toStdString()) - ^ std::hash()((uint16_t) sockAddr.getPort()); + // depending on the type of address we're looking at + + if (sockAddr.getAddress().protocol() == QAbstractSocket::IPv4Protocol) { + return std::hash()((uint32_t) sockAddr.getAddress().toIPv4Address()) + ^ std::hash()((uint16_t) sockAddr.getPort()); + } else if (sockAddr.getAddress().protocol() == QAbstractSocket::IPv6Protocol) { + // use XOR of implemented std::hash templates for new hash + return std::hash()(reinterpret_cast(sockAddr.getAddress().toIPv6Address().c)) + ^ std::hash()((uint16_t) sockAddr.getPort()); + } else { + return std::hash()(sockAddr.getAddress().toString().toStdString()) + ^ std::hash()((uint16_t) sockAddr.getPort()); + + } } }; diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt index 2056044a4b..7ab4525707 100644 --- a/tools/CMakeLists.txt +++ b/tools/CMakeLists.txt @@ -8,5 +8,8 @@ set_target_properties(scribe PROPERTIES FOLDER "Tools") add_subdirectory(udt-test) set_target_properties(udt-test PROPERTIES FOLDER "Tools") +add_subdirectory(container-test) +set_target_properties(container-test PROPERTIES FOLDER "Tools") + add_subdirectory(vhacd-util) set_target_properties(vhacd-util PROPERTIES FOLDER "Tools") diff --git a/tools/container-test/CMakeLists.txt b/tools/container-test/CMakeLists.txt new file mode 100644 index 0000000000..0eea7ddd84 --- /dev/null +++ b/tools/container-test/CMakeLists.txt @@ -0,0 +1,4 @@ +set(TARGET_NAME container-test) +setup_hifi_project() + +link_hifi_libraries(networking) \ No newline at end of file diff --git a/tools/container-test/src/main.cpp b/tools/container-test/src/main.cpp new file mode 100644 index 0000000000..7b570b4172 --- /dev/null +++ b/tools/container-test/src/main.cpp @@ -0,0 +1,84 @@ +// +// main.cpp +// tools/container-test/src +// +// Created by Stephen Birarda on 8/18/15. +// Copyright 2015 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html + +#include +#include +#include +#include +#include + +#include + +using namespace std::chrono; + +int main(int argc, char* argv[]) { + static const int NUM_ELEMENTS = 50; + + std::random_device rd; + std::mt19937 generator(rd()); + std::uniform_int_distribution<> ipDistribution(1, UINT32_MAX); + std::uniform_int_distribution<> portDistribution(1, UINT16_MAX); + + // from 1 to NUM_ELEMENTS, create a vector and unordered map with that many elements and compare how long it takes to pull the last value + for (int i = 1; i <= NUM_ELEMENTS; ++i) { + // create our vector with i elements + std::vector> vectorElements(i); + + // create our unordered map with i elements + std::unordered_map hashElements; + + HifiSockAddr lastAddress; + + // fill the structures with HifiSockAddr + for (int j = 0; j < i; ++j) { + // create a random IP address + quint32 randomNumber = ipDistribution(generator); + quint32 randomIP = (randomNumber >> 24 & 0xFF) << 24 | + (randomNumber >> 16 & 0xFF) << 16 | + (randomNumber >> 8 & 0xFF) << 8 | + (randomNumber & 0xFF); + + HifiSockAddr randomAddress(QHostAddress(randomIP), portDistribution(generator)); + + vectorElements.push_back({ randomAddress, 12 }); + hashElements.insert({ randomAddress, 12 }); + + if (j == i - 1) { + // this is the last element - store it for lookup purposes + lastAddress = randomAddress; + } + } + + // time how long it takes to get the value for the key lastAddress, for each container + auto before = high_resolution_clock::now(); + int vectorResult; + + for (auto& vi : vectorElements) { + if (vi.first == lastAddress) { + vectorResult = vi.second;; + break; + } + } + + auto vectorDuration = duration_cast(high_resolution_clock::now() - before); + + Q_UNUSED(vectorResult); + + before = high_resolution_clock::now(); + auto mi = hashElements.find(lastAddress); + int mapResult = mi->second; + auto mapDuration = duration_cast(high_resolution_clock::now() - before); + + Q_UNUSED(mapResult); + + qDebug() << i << QString("v: %1ns").arg(vectorDuration.count()) << QString("m: %2ns").arg(mapDuration.count()); + } +} +