1 //
2 // Copyright © 2019 Arm Ltd. All rights reserved.
3 // SPDX-License-Identifier: MIT
4 //
5
6 #include <armnn/Types.hpp>
7
8 #include <common/include/LabelsAndEventClasses.hpp>
9
10 #include <algorithm>
11 #include <functional>
12 #include <set>
13 #include <doctest/doctest.h>
14 #include <fmt/format.h>
15 #include <thread>
16
17 using namespace arm::pipe;
18
19 TEST_SUITE("ProfilingGuidTests")
20 {
21 TEST_CASE("GuidTest")
22 {
23 ProfilingGuid guid0(0);
24 ProfilingGuid guid1(1);
25 ProfilingGuid guid2(1);
26
27 CHECK(guid0 != guid1);
28 CHECK(guid1 == guid2);
29 CHECK(guid0 < guid1);
30 CHECK(guid0 <= guid1);
31 CHECK(guid1 <= guid2);
32 CHECK(guid1 > guid0);
33 CHECK(guid1 >= guid0);
34 CHECK(guid1 >= guid2);
35 }
36
37 TEST_CASE("StaticGuidTest")
38 {
39 ProfilingStaticGuid guid0(0);
40 ProfilingStaticGuid guid1(1);
41 ProfilingStaticGuid guid2(1);
42
43 CHECK(guid0 != guid1);
44 CHECK(guid1 == guid2);
45 CHECK(guid0 < guid1);
46 CHECK(guid0 <= guid1);
47 CHECK(guid1 <= guid2);
48 CHECK(guid1 > guid0);
49 CHECK(guid1 >= guid0);
50 CHECK(guid1 >= guid2);
51 }
52
53 TEST_CASE("DynamicGuidTest")
54 {
55 ProfilingDynamicGuid guid0(0);
56 ProfilingDynamicGuid guid1(1);
57 ProfilingDynamicGuid guid2(1);
58
59 CHECK(guid0 != guid1);
60 CHECK(guid1 == guid2);
61 CHECK(guid0 < guid1);
62 CHECK(guid0 <= guid1);
63 CHECK(guid1 <= guid2);
64 CHECK(guid1 > guid0);
65 CHECK(guid1 >= guid0);
66 CHECK(guid1 >= guid2);
67 }
68
CheckStaticGuid(uint64_t guid,uint64_t expectedGuid)69 void CheckStaticGuid(uint64_t guid, uint64_t expectedGuid)
70 {
71 CHECK(guid == expectedGuid);
72 CHECK(guid >= MIN_STATIC_GUID);
73 }
74
CheckDynamicGuid(uint64_t guid,uint64_t expectedGuid)75 void CheckDynamicGuid(uint64_t guid, uint64_t expectedGuid)
76 {
77 CHECK(guid == expectedGuid);
78 CHECK(guid < MIN_STATIC_GUID);
79 }
80
81 TEST_CASE("StaticGuidGeneratorCollisionTest")
82 {
83 ProfilingGuidGenerator generator;
84 std::set<uint64_t> guids;
85 for ( int i = 0; i < 100000; ++i )
86 {
87 std::stringstream ss;
88 ss << i;
89 std::string str = ss.str();
90 ProfilingStaticGuid guid = generator.GenerateStaticId(str.c_str());
91 if (guids.find(guid) != guids.end())
92 {
93 // If we're running on a 32bit system it is more likely to get a GUID clash over 1 million executions.
94 // We can generally detect this when the GUID turns out to be MIN_STATIC_GUID. Output a warning
95 // message rather than error in this case.
96 if (guid == ProfilingGuid(MIN_STATIC_GUID))
97 {
98 WARN("MIN_STATIC_GUID returned more than once from GenerateStaticId.");
99 }
100 else
101 {
102 FAIL(fmt::format("GUID collision occurred: {} -> {}", str, guid));
103 }
104 break;
105 }
106 guids.insert(guid);
107 }
108 }
109
110 TEST_CASE("StaticGuidGeneratorTest")
111 {
112 ProfilingGuidGenerator generator;
113
114 ProfilingStaticGuid staticGuid0 = generator.GenerateStaticId("name");
115 CheckStaticGuid(staticGuid0, LabelsAndEventClasses::NAME_GUID);
116 CHECK(staticGuid0 != generator.GenerateStaticId("Name"));
117
118 ProfilingStaticGuid staticGuid1 = generator.GenerateStaticId("type");
119 CheckStaticGuid(staticGuid1, LabelsAndEventClasses::TYPE_GUID);
120 CHECK(staticGuid1 != generator.GenerateStaticId("Type"));
121
122 ProfilingStaticGuid staticGuid2 = generator.GenerateStaticId("index");
123 CheckStaticGuid(staticGuid2, LabelsAndEventClasses::INDEX_GUID);
124 CHECK(staticGuid2 != generator.GenerateStaticId("Index"));
125 }
126
127 TEST_CASE("DynamicGuidGeneratorTest")
128 {
129 ProfilingGuidGenerator generator;
130
131 for (unsigned int i = 0; i < 100; ++i)
132 {
133 ProfilingDynamicGuid guid = generator.NextGuid();
134 CheckDynamicGuid(guid, i);
135 }
136 }
137
GenerateProfilingGUID(ProfilingGuidGenerator & guidGenerator)138 void GenerateProfilingGUID(ProfilingGuidGenerator& guidGenerator)
139 {
140 for (int i = 0; i < 1000; ++i)
141 {
142 guidGenerator.NextGuid();
143 }
144 }
145
146 TEST_CASE("ProfilingGuidThreadTest")
147 {
148 ProfilingGuidGenerator profilingGuidGenerator;
149 std::vector<std::thread> threads;
150 for (unsigned int i = 0; i < 3; ++i)
151 {
152 threads.push_back(std::thread(GenerateProfilingGUID, std::ref(profilingGuidGenerator)));
153 }
154 std::for_each(threads.begin(), threads.end(), [](std::thread& theThread)
__anonfdc18dd50102(std::thread& theThread) 155 {
156 theThread.join();
157 });
158
159 uint64_t guid = profilingGuidGenerator.NextGuid();
160 CHECK(guid == 3000u);
161 }
162
163 }
164