From dbdd1b438815606bd423cbcfb95d51a3dd206683 Mon Sep 17 00:00:00 2001 From: Narumol Prangnawarat Date: Fri, 15 Nov 2019 17:38:44 +0000 Subject: IVGCVSW-3980 Implementation of Guid generator * Improve implementation of Guid Generator to separate the range of Static Guid and Dynamic Guid * Unit tests to ensure non-collision Signed-off-by: Narumol Prangnawarat Change-Id: I4ad1a75ea0b1f37155da0decafb51fc5a61e4187 --- include/armnn/Types.hpp | 2 + src/profiling/ProfilingGuidGenerator.hpp | 17 ++-- src/profiling/test/ProfilingGuidTest.cpp | 91 ++++++++++++++++++++++ src/profiling/test/SendTimelinePacketTests.cpp | 13 ++-- src/profiling/test/TimelineUtilityMethodsTests.cpp | 27 +++++-- 5 files changed, 129 insertions(+), 21 deletions(-) diff --git a/include/armnn/Types.hpp b/include/armnn/Types.hpp index 94f45302c7..4e80c3ccda 100644 --- a/include/armnn/Types.hpp +++ b/include/armnn/Types.hpp @@ -229,6 +229,8 @@ using DebugCallbackFunction = std::function= MIN_STATIC_GUID) + { + // Reset the sequence to 0 when it reaches the upper bound of dynamic guid + m_Sequence = 0; + } return guid; } /// Create a ProfilingStaticGuid based on a hash of the string - // NOTE: dummy implementation for the moment inline ProfilingStaticGuid GenerateStaticId(const std::string& str) override { - uint64_t guid = static_cast(m_StringHasher(str)); - return guid; + uint64_t staticHash = m_Hash(str) | MIN_STATIC_GUID; + return ProfilingStaticGuid(staticHash); } private: - std::hash m_StringHasher; uint64_t m_Sequence; + std::hash m_Hash; }; } // namespace profiling diff --git a/src/profiling/test/ProfilingGuidTest.cpp b/src/profiling/test/ProfilingGuidTest.cpp index f72cc1c452..c0dd986c8a 100644 --- a/src/profiling/test/ProfilingGuidTest.cpp +++ b/src/profiling/test/ProfilingGuidTest.cpp @@ -5,6 +5,11 @@ #include +#include "LabelsAndEventClasses.hpp" +#include "ProfilingGuidGenerator.hpp" + +#include + #include using namespace armnn::profiling; @@ -59,4 +64,90 @@ BOOST_AUTO_TEST_CASE(DynamicGuidTest) BOOST_TEST(guid1 >= guid2); } +std::string GenerateRandomString() +{ + // Random a string lengh from 3 - 100 + int minLength = 3; + int maxLength = 100; + + // Random a character from lower case alphabets, upper case alphabets, numbers and special characters + int minAscii = 32; // space 32 + int maxAscii = 126; // ~ + + int stringLen = rand() % (maxLength - minLength + 1) + minLength; + char str[stringLen + 1]; + for (int i = 0; i < stringLen; ++i) + { + int randAscii = rand() % (maxAscii - minAscii + 1) + minAscii; + str[i] = char(randAscii); + } + str[stringLen] = '\0'; + return std::string(str); +} + +void CheckStaticGuid(uint64_t guid, uint64_t expectedGuid) +{ + BOOST_TEST(guid == expectedGuid); + BOOST_TEST(guid >= MIN_STATIC_GUID); +} + +void CheckDynamicGuid(uint64_t guid, uint64_t expectedGuid) +{ + BOOST_TEST(guid == expectedGuid); + BOOST_TEST(guid < MIN_STATIC_GUID); +} + +BOOST_AUTO_TEST_CASE(StaticGuidGeneratorCollisionTest) +{ + ProfilingGuidGenerator generator; + std::set guids; + std::set strs; + std::map guidMap; + int collision = 0; + for (int i = 0; i < 1000000; ++i) + { + std::string str = GenerateRandomString(); + if(strs.find(str) != strs.end()) + { + continue; + } + strs.insert(str); + ProfilingStaticGuid guid = generator.GenerateStaticId(str.c_str()); + if (guids.find(guid) != guids.end()) + { + collision++; + } + guids.insert(guid); + } + BOOST_TEST(collision == 0); +} + +BOOST_AUTO_TEST_CASE(StaticGuidGeneratorTest) +{ + ProfilingGuidGenerator generator; + + ProfilingStaticGuid staticGuid0 = generator.GenerateStaticId("name"); + CheckStaticGuid(staticGuid0, LabelsAndEventClasses::NAME_GUID); + BOOST_TEST(staticGuid0 != generator.GenerateStaticId("Name")); + + ProfilingStaticGuid staticGuid1 = generator.GenerateStaticId("type"); + CheckStaticGuid(staticGuid1, LabelsAndEventClasses::TYPE_GUID); + BOOST_TEST(staticGuid1 != generator.GenerateStaticId("Type")); + + ProfilingStaticGuid staticGuid2 = generator.GenerateStaticId("index"); + CheckStaticGuid(staticGuid2, LabelsAndEventClasses::INDEX_GUID); + BOOST_TEST(staticGuid2 != generator.GenerateStaticId("Index")); +} + +BOOST_AUTO_TEST_CASE(DynamicGuidGeneratorTest) +{ + ProfilingGuidGenerator generator; + + for (unsigned int i = 0; i < 100; ++i) + { + ProfilingDynamicGuid guid = generator.NextGuid(); + CheckDynamicGuid(guid, i); + } +} + BOOST_AUTO_TEST_SUITE_END() diff --git a/src/profiling/test/SendTimelinePacketTests.cpp b/src/profiling/test/SendTimelinePacketTests.cpp index 26b49dfb18..771e117955 100644 --- a/src/profiling/test/SendTimelinePacketTests.cpp +++ b/src/profiling/test/SendTimelinePacketTests.cpp @@ -415,10 +415,9 @@ BOOST_AUTO_TEST_CASE(GetGuidsFromProfilingService) ProfilingService& profilingService = ProfilingService::Instance(); profilingService.ResetExternalProfilingOptions(options, true); ProfilingStaticGuid staticGuid = profilingService.GenerateStaticId("dummy"); - // TODO this will change again... std::hash hasher; uint64_t hash = static_cast(hasher("dummy")); - ProfilingStaticGuid expectedStaticValue(hash); + ProfilingStaticGuid expectedStaticValue(hash | MIN_STATIC_GUID); BOOST_CHECK(staticGuid == expectedStaticValue); ProfilingDynamicGuid dynamicGuid = profilingService.NextGuid(); uint64_t dynamicGuidValue = static_cast(dynamicGuid); @@ -448,23 +447,23 @@ BOOST_AUTO_TEST_CASE(CheckStaticGuidsAndEvents) std::hash hasher; uint64_t hash = static_cast(hasher(LabelsAndEventClasses::NAME_LABEL)); - ProfilingStaticGuid expectedNameGuid(hash); + ProfilingStaticGuid expectedNameGuid(hash | MIN_STATIC_GUID); BOOST_CHECK(LabelsAndEventClasses::NAME_GUID == expectedNameGuid); hash = static_cast(hasher(LabelsAndEventClasses::TYPE_LABEL)); - ProfilingStaticGuid expectedTypeGuid(hash); + ProfilingStaticGuid expectedTypeGuid(hash | MIN_STATIC_GUID); BOOST_CHECK(LabelsAndEventClasses::TYPE_GUID == expectedTypeGuid); hash = static_cast(hasher(LabelsAndEventClasses::INDEX_LABEL)); - ProfilingStaticGuid expectedIndexGuid(hash); + ProfilingStaticGuid expectedIndexGuid(hash | MIN_STATIC_GUID); BOOST_CHECK(LabelsAndEventClasses::INDEX_GUID == expectedIndexGuid); hash = static_cast(hasher("ARMNN_PROFILING_SOL")); - ProfilingStaticGuid expectedSol(hash); + ProfilingStaticGuid expectedSol(hash | MIN_STATIC_GUID); BOOST_CHECK(LabelsAndEventClasses::ARMNN_PROFILING_SOL_EVENT_CLASS == expectedSol); hash = static_cast(hasher("ARMNN_PROFILING_EOL")); - ProfilingStaticGuid expectedEol(hash); + ProfilingStaticGuid expectedEol(hash | MIN_STATIC_GUID); BOOST_CHECK(LabelsAndEventClasses::ARMNN_PROFILING_EOL_EVENT_CLASS == expectedEol); } diff --git a/src/profiling/test/TimelineUtilityMethodsTests.cpp b/src/profiling/test/TimelineUtilityMethodsTests.cpp index f784afc6ef..2eb96e62d1 100644 --- a/src/profiling/test/TimelineUtilityMethodsTests.cpp +++ b/src/profiling/test/TimelineUtilityMethodsTests.cpp @@ -368,6 +368,9 @@ BOOST_AUTO_TEST_CASE(CreateTypedLabelTest) SendTimelinePacket sendTimelinePacket(mockBufferManager); TimelineUtilityMethods timelineUtilityMethods(sendTimelinePacket); + // Generate first guid to ensure that the named typed entity guid is not 0 on local single test. + ProfilingService::Instance().NextGuid(); + ProfilingGuid entityGuid(123); const std::string entityName = "some entity"; ProfilingStaticGuid labelTypeGuid(456); @@ -475,6 +478,9 @@ BOOST_AUTO_TEST_CASE(CreateNamedTypedChildEntityTest) const std::string entityName = "some entity"; const std::string entityType = "some type"; + // Generate first guid to ensure that the named typed entity guid is not 0 on local single test. + ProfilingService::Instance().NextGuid(); + BOOST_CHECK_THROW(timelineUtilityMethods.CreateNamedTypedChildEntity(parentEntityGuid, "", entityType), InvalidArgumentException); BOOST_CHECK_THROW(timelineUtilityMethods.CreateNamedTypedChildEntity(parentEntityGuid, entityName, ""), @@ -559,6 +565,9 @@ BOOST_AUTO_TEST_CASE(DeclareLabelTest) SendTimelinePacket sendTimelinePacket(mockBufferManager); TimelineUtilityMethods timelineUtilityMethods(sendTimelinePacket); + // Generate first guid to ensure that the named typed entity guid is not 0 on local single test. + ProfilingService::Instance().NextGuid(); + // Try declaring an invalid (empty) label BOOST_CHECK_THROW(timelineUtilityMethods.DeclareLabel(""), InvalidArgumentException); @@ -569,15 +578,13 @@ BOOST_AUTO_TEST_CASE(DeclareLabelTest) const std::string labelName = "valid label"; ProfilingGuid labelGuid = 0; BOOST_CHECK_NO_THROW(labelGuid = timelineUtilityMethods.DeclareLabel(labelName)); - // TODO when the implementation of the profiling GUID generator is done, enable the following test - //BOOST_CHECK(labelGuid != ProfilingGuid(0)); + BOOST_CHECK(labelGuid != ProfilingGuid(0)); - // TODO when the implementation of the profiling GUID generator is done, enable the following tests // Try adding the same label as before - //ProfilingGuid newLabelGuid = 0; - //BOOST_CHECK_NO_THROW(labelGuid = timelineUtilityMethods.DeclareLabel(labelName)); - //BOOST_CHECK(newLabelGuid != ProfilingGuid(0)); - //BOOST_CHECK(newLabelGuid == labelGuid); + ProfilingGuid newLabelGuid = 0; + BOOST_CHECK_NO_THROW(newLabelGuid = timelineUtilityMethods.DeclareLabel(labelName)); + BOOST_CHECK(newLabelGuid != ProfilingGuid(0)); + BOOST_CHECK(newLabelGuid == labelGuid); } BOOST_AUTO_TEST_CASE(CreateNameTypeEntityInvalidTest) @@ -603,6 +610,9 @@ BOOST_AUTO_TEST_CASE(CreateNameTypeEntityTest) const std::string entityName = "Entity0"; const std::string entityType = "Type0"; + // Generate first guid to ensure that the named typed entity guid is not 0 on local single test. + ProfilingService::Instance().NextGuid(); + ProfilingDynamicGuid guid = timelineUtilityMethods.CreateNamedTypedEntity(entityName, entityType); BOOST_CHECK(guid != ProfilingGuid(0)); @@ -673,6 +683,9 @@ BOOST_AUTO_TEST_CASE(RecordEventTest) SendTimelinePacket sendTimelinePacket(mockBufferManager); TimelineUtilityMethods timelineUtilityMethods(sendTimelinePacket); + // Generate first guid to ensure that the named typed entity guid is not 0 on local single test. + ProfilingService::Instance().NextGuid(); + ProfilingGuid entityGuid(123); ProfilingStaticGuid eventClassGuid(456); ProfilingDynamicGuid eventGuid(0); -- cgit v1.2.1