• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright © 2019 Arm Ltd and Contributors. All rights reserved.
3 // SPDX-License-Identifier: MIT
4 //
5 
6 #include <common/include/CommandHandlerFunctor.hpp>
7 #include <common/include/CommonProfilingUtils.hpp>
8 #include <server/include/timelineDecoder/TimelineCaptureCommandHandler.hpp>
9 #include <server/include/timelineDecoder/TimelineDirectoryCaptureCommandHandler.hpp>
10 #include <server/include/timelineDecoder/TimelineDecoder.hpp>
11 
12 #include <BufferManager.hpp>
13 #include <Threads.hpp>
14 #include <ProfilingService.hpp>
15 #include <PacketBuffer.hpp>
16 #include <TimelinePacketWriterFactory.hpp>
17 
18 #include <boost/test/test_tools.hpp>
19 #include <boost/test/unit_test_suite.hpp>
20 
BOOST_AUTO_TEST_SUITE(TimelineDecoderTests)21 BOOST_AUTO_TEST_SUITE(TimelineDecoderTests)
22 
23 void SendTimelinePacketToCommandHandler(const unsigned char* packetBuffer,
24                                         arm::pipe::CommandHandlerFunctor& CommandHandler)
25 {
26     uint32_t uint32_t_size = sizeof(uint32_t);
27     unsigned int offset = 0;
28 
29     uint32_t header[2];
30     header[0] = arm::pipe::ReadUint32(packetBuffer, offset);
31     offset += uint32_t_size;
32     header[1] = arm::pipe::ReadUint32(packetBuffer, offset);
33     offset += uint32_t_size;
34     uint32_t PacketDataLength  = header[1] & 0x00FFFFFF;
35 
36     auto uniquePacketData = std::make_unique<unsigned char[]>(PacketDataLength);
37     std::memcpy(uniquePacketData.get(), packetBuffer + offset, PacketDataLength);
38 
39     arm::pipe::Packet packet(header[0], PacketDataLength, uniquePacketData);
40 
41     BOOST_CHECK(std::memcmp(packetBuffer + offset, packet.GetData(), packet.GetLength()) == 0);
42 
43     CommandHandler(packet);
44 }
45 
PushEntity(arm::pipe::TimelineDecoder::Model & model,const arm::pipe::ITimelineDecoder::Entity entity)46 void PushEntity(arm::pipe::TimelineDecoder::Model& model, const arm::pipe::ITimelineDecoder::Entity entity)
47 {
48     model.m_Entities.emplace_back(entity);
49 }
50 
PushEventClass(arm::pipe::TimelineDecoder::Model & model,const arm::pipe::ITimelineDecoder::EventClass eventClass)51 void PushEventClass(arm::pipe::TimelineDecoder::Model& model, const arm::pipe::ITimelineDecoder::EventClass eventClass)
52 {
53     model.m_EventClasses.emplace_back(eventClass);
54 }
55 
PushEvent(arm::pipe::TimelineDecoder::Model & model,const arm::pipe::ITimelineDecoder::Event event)56 void PushEvent(arm::pipe::TimelineDecoder::Model& model, const arm::pipe::ITimelineDecoder::Event event)
57 {
58     model.m_Events.emplace_back(event);
59 }
60 
PushLabel(arm::pipe::TimelineDecoder::Model & model,const arm::pipe::ITimelineDecoder::Label label)61 void PushLabel(arm::pipe::TimelineDecoder::Model& model, const arm::pipe::ITimelineDecoder::Label label)
62 {
63     model.m_Labels.emplace_back(label);
64 }
65 
PushRelationship(arm::pipe::TimelineDecoder::Model & model,const arm::pipe::ITimelineDecoder::Relationship relationship)66 void PushRelationship(arm::pipe::TimelineDecoder::Model& model,
67                       const arm::pipe::ITimelineDecoder::Relationship relationship)
68 {
69     model.m_Relationships.emplace_back(relationship);
70 }
71 
BOOST_AUTO_TEST_CASE(TimelineDirectoryTest)72 BOOST_AUTO_TEST_CASE(TimelineDirectoryTest)
73 {
74     uint32_t uint8_t_size  = sizeof(uint8_t);
75     uint32_t uint32_t_size = sizeof(uint32_t);
76     uint32_t uint64_t_size = sizeof(uint64_t);
77 
78     armnn::profiling::BufferManager bufferManager(5);
79     armnn::profiling::TimelinePacketWriterFactory timelinePacketWriterFactory(bufferManager);
80 
81     std::unique_ptr<armnn::profiling::ISendTimelinePacket> sendTimelinePacket =
82             timelinePacketWriterFactory.GetSendTimelinePacket();
83 
84     arm::pipe::PacketVersionResolver packetVersionResolver;
85 
86     arm::pipe::TimelineDecoder timelineDecoder;
87     arm::pipe::TimelineCaptureCommandHandler timelineCaptureCommandHandler(
88             1, 1, packetVersionResolver.ResolvePacketVersion(1, 1).GetEncodedValue(), timelineDecoder);
89 
90     arm::pipe::TimelineDirectoryCaptureCommandHandler timelineDirectoryCaptureCommandHandler(
91             1, 0, packetVersionResolver.ResolvePacketVersion(1, 0).GetEncodedValue(),
92             timelineCaptureCommandHandler, true);
93 
94     sendTimelinePacket->SendTimelineMessageDirectoryPackage();
95     sendTimelinePacket->Commit();
96 
97     std::vector<arm::pipe::SwTraceMessage> swTraceBufferMessages;
98 
99     unsigned int offset = uint32_t_size * 2;
100 
101     std::unique_ptr<armnn::profiling::IPacketBuffer> packetBuffer = bufferManager.GetReadableBuffer();
102 
103     uint8_t readStreamVersion = ReadUint8(packetBuffer, offset);
104     BOOST_CHECK(readStreamVersion == 4);
105     offset += uint8_t_size;
106     uint8_t readPointerBytes = ReadUint8(packetBuffer, offset);
107     BOOST_CHECK(readPointerBytes == uint64_t_size);
108     offset += uint8_t_size;
109     uint8_t readThreadIdBytes = ReadUint8(packetBuffer, offset);
110     BOOST_CHECK(readThreadIdBytes == armnn::profiling::ThreadIdSize);
111     offset += uint8_t_size;
112 
113     uint32_t declarationSize = arm::pipe::ReadUint32(packetBuffer->GetReadableData(), offset);
114     offset += uint32_t_size;
115     for(uint32_t i = 0; i < declarationSize; ++i)
116     {
117         swTraceBufferMessages.push_back(arm::pipe::ReadSwTraceMessage(packetBuffer->GetReadableData(),
118                                                                       offset,
119                                                                       packetBuffer->GetSize()));
120     }
121 
122     SendTimelinePacketToCommandHandler(packetBuffer->GetReadableData(), timelineDirectoryCaptureCommandHandler);
123 
124     for(uint32_t index = 0; index < declarationSize; ++index)
125     {
126         arm::pipe::SwTraceMessage& bufferMessage = swTraceBufferMessages[index];
127         arm::pipe::SwTraceMessage& handlerMessage = timelineDirectoryCaptureCommandHandler.m_SwTraceMessages[index];
128 
129         BOOST_CHECK(bufferMessage.m_Name == handlerMessage.m_Name);
130         BOOST_CHECK(bufferMessage.m_UiName == handlerMessage.m_UiName);
131         BOOST_CHECK(bufferMessage.m_Id == handlerMessage.m_Id);
132 
133         BOOST_CHECK(bufferMessage.m_ArgTypes.size() == handlerMessage.m_ArgTypes.size());
134         for(uint32_t i = 0; i < bufferMessage.m_ArgTypes.size(); ++i)
135         {
136             BOOST_CHECK(bufferMessage.m_ArgTypes[i] == handlerMessage.m_ArgTypes[i]);
137         }
138 
139         BOOST_CHECK(bufferMessage.m_ArgNames.size() == handlerMessage.m_ArgNames.size());
140         for(uint32_t i = 0; i < bufferMessage.m_ArgNames.size(); ++i)
141         {
142             BOOST_CHECK(bufferMessage.m_ArgNames[i] == handlerMessage.m_ArgNames[i]);
143         }
144     }
145 }
146 
BOOST_AUTO_TEST_CASE(TimelineCaptureTest)147 BOOST_AUTO_TEST_CASE(TimelineCaptureTest)
148 {
149     armnn::profiling::BufferManager bufferManager(50);
150     armnn::profiling::TimelinePacketWriterFactory timelinePacketWriterFactory(bufferManager);
151 
152     std::unique_ptr<armnn::profiling::ISendTimelinePacket> sendTimelinePacket =
153         timelinePacketWriterFactory.GetSendTimelinePacket();
154 
155     arm::pipe::PacketVersionResolver packetVersionResolver;
156 
157     arm::pipe::TimelineDecoder timelineDecoder;
158     const arm::pipe::TimelineDecoder::Model& model = timelineDecoder.GetModel();
159 
160 
161     arm::pipe::TimelineCaptureCommandHandler timelineCaptureCommandHandler(
162         1, 1, packetVersionResolver.ResolvePacketVersion(1, 1).GetEncodedValue(), timelineDecoder,
163         armnn::profiling::ThreadIdSize);
164 
165     using Status = arm::pipe::ITimelineDecoder::TimelineStatus;
166     BOOST_CHECK(timelineDecoder.SetEntityCallback(PushEntity)             == Status::TimelineStatus_Success);
167     BOOST_CHECK(timelineDecoder.SetEventClassCallback(PushEventClass)     == Status::TimelineStatus_Success);
168     BOOST_CHECK(timelineDecoder.SetEventCallback(PushEvent)               == Status::TimelineStatus_Success);
169     BOOST_CHECK(timelineDecoder.SetLabelCallback(PushLabel)               == Status::TimelineStatus_Success);
170     BOOST_CHECK(timelineDecoder.SetRelationshipCallback(PushRelationship) == Status::TimelineStatus_Success);
171 
172     const uint64_t entityGuid = 111111u;
173     const uint64_t eventClassGuid = 22222u;
174     const uint64_t eventClassNameGuid = 22322u;
175     const uint64_t timestamp = 33333u;
176     const uint64_t eventGuid = 44444u;
177 
178     const int threadId = armnnUtils::Threads::GetCurrentThreadId();
179 
180     // need to do a bit of work here to extract the value from threadId
181     unsigned char* uCharThreadId = new unsigned char[armnn::profiling::ThreadIdSize]();;
182     uint64_t uint64ThreadId;
183 
184     arm::pipe::WriteBytes(uCharThreadId, 0, &threadId, armnn::profiling::ThreadIdSize);
185 
186     if (armnn::profiling::ThreadIdSize == 4)
187     {
188         uint64ThreadId =  arm::pipe::ReadUint32(uCharThreadId, 0);
189     }
190     else if (armnn::profiling::ThreadIdSize == 8)
191     {
192         uint64ThreadId =  arm::pipe::ReadUint64(uCharThreadId, 0);
193     }
194     delete[] uCharThreadId;
195 
196     const uint64_t labelGuid = 66666u;
197     std::string labelName = "test_label";
198 
199     const uint64_t relationshipGuid = 77777u;
200     const uint64_t headGuid = 888888u;
201     const uint64_t tailGuid = 999999u;
202 
203     for (int i = 0; i < 10; ++i)
204     {
205         // Send entity
206         sendTimelinePacket->SendTimelineEntityBinaryPacket(entityGuid);
207         sendTimelinePacket->Commit();
208         SendTimelinePacketToCommandHandler(bufferManager.GetReadableBuffer()->GetReadableData(),
209                                            timelineCaptureCommandHandler);
210 
211         // Send event class
212         sendTimelinePacket->SendTimelineEventClassBinaryPacket(eventClassGuid, eventClassNameGuid);
213         sendTimelinePacket->Commit();
214         SendTimelinePacketToCommandHandler(bufferManager.GetReadableBuffer()->GetReadableData(),
215                                            timelineCaptureCommandHandler);
216 
217         // Send event
218         sendTimelinePacket->SendTimelineEventBinaryPacket(timestamp, threadId, eventGuid);
219         sendTimelinePacket->Commit();
220         SendTimelinePacketToCommandHandler(bufferManager.GetReadableBuffer()->GetReadableData(),
221                                            timelineCaptureCommandHandler);
222 
223         // Send label
224         sendTimelinePacket->SendTimelineLabelBinaryPacket(labelGuid, labelName);
225         sendTimelinePacket->Commit();
226         SendTimelinePacketToCommandHandler(bufferManager.GetReadableBuffer()->GetReadableData(),
227                                            timelineCaptureCommandHandler);
228 
229         // Send relationship
230         armnn::profiling::ProfilingRelationshipType relationshipType =
231             armnn::profiling::ProfilingRelationshipType::DataLink;
232         sendTimelinePacket->SendTimelineRelationshipBinaryPacket(relationshipType,
233                                                                  relationshipGuid,
234                                                                  headGuid,
235                                                                  tailGuid,
236                                                                  0);
237         sendTimelinePacket->Commit();
238         SendTimelinePacketToCommandHandler(bufferManager.GetReadableBuffer()->GetReadableData(),
239                                            timelineCaptureCommandHandler);
240     }
241 
242     for (unsigned long i = 0; i < 10; ++i)
243     {
244         BOOST_CHECK(model.m_Entities[i].m_Guid == entityGuid);
245 
246         BOOST_CHECK(model.m_EventClasses[i].m_Guid == eventClassGuid);
247 
248         BOOST_CHECK(model.m_Events[i].m_TimeStamp == timestamp);
249         BOOST_CHECK(model.m_Events[i].m_ThreadId == uint64ThreadId);
250         BOOST_CHECK(model.m_Events[i].m_Guid == eventGuid);
251 
252         BOOST_CHECK(model.m_Labels[i].m_Guid == labelGuid);
253         BOOST_CHECK(model.m_Labels[i].m_Name == labelName);
254 
255         BOOST_CHECK(model.m_Relationships[i].m_RelationshipType ==
256             arm::pipe::ITimelineDecoder::RelationshipType::DataLink);
257         BOOST_CHECK(model.m_Relationships[i].m_Guid == relationshipGuid);
258         BOOST_CHECK(model.m_Relationships[i].m_HeadGuid == headGuid);
259         BOOST_CHECK(model.m_Relationships[i].m_TailGuid == tailGuid);
260     }
261 }
262 
BOOST_AUTO_TEST_CASE(TimelineCaptureTestMultipleStringsInBuffer)263 BOOST_AUTO_TEST_CASE(TimelineCaptureTestMultipleStringsInBuffer)
264 {
265     armnn::profiling::BufferManager               bufferManager(50);
266     armnn::profiling::TimelinePacketWriterFactory timelinePacketWriterFactory(bufferManager);
267 
268     std::unique_ptr<armnn::profiling::ISendTimelinePacket> sendTimelinePacket =
269                                                         timelinePacketWriterFactory.GetSendTimelinePacket();
270 
271     arm::pipe::PacketVersionResolver packetVersionResolver;
272 
273     arm::pipe::TimelineDecoder timelineDecoder;
274     const arm::pipe::TimelineDecoder::Model& model = timelineDecoder.GetModel();
275 
276     arm::pipe::TimelineCaptureCommandHandler timelineCaptureCommandHandler(
277         1, 1, packetVersionResolver.ResolvePacketVersion(1, 1).GetEncodedValue(), timelineDecoder,
278         armnn::profiling::ThreadIdSize);
279 
280     using Status = arm::pipe::TimelineDecoder::TimelineStatus;
281     BOOST_CHECK(timelineDecoder.SetEntityCallback(PushEntity) == Status::TimelineStatus_Success);
282     BOOST_CHECK(timelineDecoder.SetEventClassCallback(PushEventClass) == Status::TimelineStatus_Success);
283     BOOST_CHECK(timelineDecoder.SetEventCallback(PushEvent) == Status::TimelineStatus_Success);
284     BOOST_CHECK(timelineDecoder.SetLabelCallback(PushLabel) == Status::TimelineStatus_Success);
285     BOOST_CHECK(timelineDecoder.SetRelationshipCallback(PushRelationship) == Status::TimelineStatus_Success);
286 
287     const uint64_t entityGuid         = 111111u;
288     const uint64_t eventClassGuid     = 22222u;
289     const uint64_t eventClassNameGuid = 22322u;
290     const uint64_t timestamp          = 33333u;
291     const uint64_t eventGuid          = 44444u;
292 
293     const int threadId = armnnUtils::Threads::GetCurrentThreadId();
294 
295     // need to do a bit of work here to extract the value from threadId
296     unsigned char* uCharThreadId = new unsigned char[armnn::profiling::ThreadIdSize]();
297     uint64_t uint64ThreadId;
298 
299     arm::pipe::WriteBytes(uCharThreadId, 0, &threadId, armnn::profiling::ThreadIdSize);
300 
301     if ( armnn::profiling::ThreadIdSize == 4 )
302     {
303         uint64ThreadId = arm::pipe::ReadUint32(uCharThreadId, 0);
304     }
305     else if ( armnn::profiling::ThreadIdSize == 8 )
306     {
307         uint64ThreadId = arm::pipe::ReadUint64(uCharThreadId, 0);
308     }
309     delete[] uCharThreadId;
310 
311     const uint64_t labelGuid  = 66666u;
312     std::string    labelName  = "test_label";
313     std::string    labelName2 = "test_label2";
314     std::string    labelName3 = "test_label32";
315 
316     const uint64_t relationshipGuid = 77777u;
317     const uint64_t headGuid         = 888888u;
318     const uint64_t tailGuid         = 999999u;
319 
320     // Check with multiple messages in the same buffer
321     for ( int i = 0; i < 9; ++i )
322     {
323         // Send entity
324         sendTimelinePacket->SendTimelineEntityBinaryPacket(entityGuid);
325         // Send event class
326         sendTimelinePacket->SendTimelineEventClassBinaryPacket(eventClassGuid, eventClassNameGuid);
327         // Send event
328         sendTimelinePacket->SendTimelineEventBinaryPacket(timestamp, threadId, eventGuid);
329         // Send label
330         sendTimelinePacket->SendTimelineLabelBinaryPacket(labelGuid, labelName);
331         sendTimelinePacket->SendTimelineLabelBinaryPacket(labelGuid, labelName2);
332         sendTimelinePacket->SendTimelineLabelBinaryPacket(labelGuid, labelName3);
333         // Send relationship
334         armnn::profiling::ProfilingRelationshipType relationshipType =
335             armnn::profiling::ProfilingRelationshipType::DataLink;
336         sendTimelinePacket->SendTimelineRelationshipBinaryPacket(relationshipType,
337                                                                  relationshipGuid,
338                                                                  headGuid,
339                                                                  tailGuid,
340                                                                  0);
341     }
342 
343     sendTimelinePacket->Commit();
344     SendTimelinePacketToCommandHandler(bufferManager.GetReadableBuffer()->GetReadableData(),
345                                        timelineCaptureCommandHandler);
346 
347     for ( unsigned long i = 0; i < 9; ++i )
348     {
349         BOOST_CHECK(model.m_Entities[i].m_Guid == entityGuid);
350 
351         BOOST_CHECK(model.m_EventClasses[i].m_Guid == eventClassGuid);
352 
353         BOOST_CHECK(model.m_Labels[i].m_Guid == labelGuid);
354 
355         BOOST_CHECK(model.m_Events[i].m_TimeStamp == timestamp);
356         BOOST_CHECK(model.m_Events[i].m_ThreadId == uint64ThreadId);
357         BOOST_CHECK(model.m_Events[i].m_Guid == eventGuid);
358 
359         BOOST_CHECK(model.m_Relationships[i].m_RelationshipType ==
360             arm::pipe::ITimelineDecoder::RelationshipType::DataLink);
361         BOOST_CHECK(model.m_Relationships[i].m_Guid == relationshipGuid);
362         BOOST_CHECK(model.m_Relationships[i].m_HeadGuid == headGuid);
363         BOOST_CHECK(model.m_Relationships[i].m_TailGuid == tailGuid);
364     }
365     for ( unsigned long i = 0; i < 9; i += 3 )
366     {
367         BOOST_CHECK(model.m_Labels[i].m_Name == labelName);
368         BOOST_CHECK(model.m_Labels[i+1].m_Name == labelName2);
369         BOOST_CHECK(model.m_Labels[i+2].m_Name == labelName3);
370     }
371 }
372 
373 BOOST_AUTO_TEST_SUITE_END()
374