1 //
2 // Copyright © 2019 Arm Ltd and Contributors. All rights reserved.
3 // SPDX-License-Identifier: MIT
4 //
5 #include "ProfilingUtils.hpp"
6
7 #include <client/include/TimelineUtilityMethods.hpp>
8
9 #include <common/include/LabelsAndEventClasses.hpp>
10 #include <common/include/Threads.hpp>
11
12 namespace arm
13 {
14
15 namespace pipe
16 {
17
GetTimelineUtils(IProfilingService & profilingService)18 std::unique_ptr<TimelineUtilityMethods> TimelineUtilityMethods::GetTimelineUtils(IProfilingService& profilingService)
19 {
20 if (profilingService.GetCurrentState() == ProfilingState::Active && profilingService.IsTimelineReportingEnabled())
21 {
22 std::unique_ptr<ISendTimelinePacket> sendTimelinepacket = profilingService.GetSendTimelinePacket();
23 return std::make_unique<TimelineUtilityMethods>(sendTimelinepacket);
24 }
25 else
26 {
27 std::unique_ptr<TimelineUtilityMethods> empty;
28 return empty;
29 }
30 }
31
32
SendWellKnownLabelsAndEventClasses(ISendTimelinePacket & timelinePacket)33 void TimelineUtilityMethods::SendWellKnownLabelsAndEventClasses(ISendTimelinePacket& timelinePacket)
34 {
35 // Send the "name" label, this call throws in case of error
36 timelinePacket.SendTimelineLabelBinaryPacket(LabelsAndEventClasses::NAME_GUID,
37 LabelsAndEventClasses::NAME_LABEL);
38
39 // Send the "type" label, this call throws in case of error
40 timelinePacket.SendTimelineLabelBinaryPacket(LabelsAndEventClasses::TYPE_GUID,
41 LabelsAndEventClasses::TYPE_LABEL);
42
43 // Send the "index" label, this call throws in case of error
44 timelinePacket.SendTimelineLabelBinaryPacket(LabelsAndEventClasses::INDEX_GUID,
45 LabelsAndEventClasses::INDEX_LABEL);
46
47 // Send the "backendId" label, this call throws in case of error
48 timelinePacket.SendTimelineLabelBinaryPacket(LabelsAndEventClasses::BACKENDID_GUID,
49 LabelsAndEventClasses::BACKENDID_LABEL);
50
51 // Send the "child" label, this call throws in case of error
52 timelinePacket.SendTimelineLabelBinaryPacket(LabelsAndEventClasses::CHILD_GUID,
53 LabelsAndEventClasses::CHILD_LABEL);
54
55 // Send the "execution_of" label, this call throws in case of error
56 timelinePacket.SendTimelineLabelBinaryPacket(LabelsAndEventClasses::EXECUTION_OF_GUID,
57 LabelsAndEventClasses::EXECUTION_OF_LABEL);
58
59 // Send the "process_id" label, this call throws in case of error
60 timelinePacket.SendTimelineLabelBinaryPacket(LabelsAndEventClasses::PROCESS_ID_GUID,
61 LabelsAndEventClasses::PROCESS_ID_LABEL);
62
63 // Send the "layer" label, this call throws in case of error
64 timelinePacket.SendTimelineLabelBinaryPacket(LabelsAndEventClasses::LAYER_GUID,
65 LabelsAndEventClasses::LAYER);
66
67 // Send the "workload" label, this call throws in case of error
68 timelinePacket.SendTimelineLabelBinaryPacket(LabelsAndEventClasses::WORKLOAD_GUID,
69 LabelsAndEventClasses::WORKLOAD);
70
71 // Send the "network" label, this call throws in case of error
72 timelinePacket.SendTimelineLabelBinaryPacket(LabelsAndEventClasses::NETWORK_GUID,
73 LabelsAndEventClasses::NETWORK);
74
75 // Send the "connection" label, this call throws in case of error
76 timelinePacket.SendTimelineLabelBinaryPacket(LabelsAndEventClasses::CONNECTION_GUID,
77 LabelsAndEventClasses::CONNECTION);
78
79 // Send the "inference" label, this call throws in case of error
80 timelinePacket.SendTimelineLabelBinaryPacket(LabelsAndEventClasses::INFERENCE_GUID,
81 LabelsAndEventClasses::INFERENCE);
82
83 // Send the "workload_execution" label, this call throws in case of error
84 timelinePacket.SendTimelineLabelBinaryPacket(LabelsAndEventClasses::WORKLOAD_EXECUTION_GUID,
85 LabelsAndEventClasses::WORKLOAD_EXECUTION);
86
87 // Send the "start of life" event class, this call throws in case of error
88 timelinePacket.SendTimelineLabelBinaryPacket(LabelsAndEventClasses::ARMNN_PROFILING_SOL_EVENT_CLASS_NAME_GUID,
89 LabelsAndEventClasses::ARMNN_PROFILING_SOL_EVENT_CLASS_NAME);
90 timelinePacket.SendTimelineEventClassBinaryPacket(LabelsAndEventClasses::ARMNN_PROFILING_SOL_EVENT_CLASS,
91 LabelsAndEventClasses::ARMNN_PROFILING_SOL_EVENT_CLASS_NAME_GUID);
92
93 // Send the "end of life" event class, this call throws in case of error
94 timelinePacket.SendTimelineLabelBinaryPacket(LabelsAndEventClasses::ARMNN_PROFILING_EOL_EVENT_CLASS_NAME_GUID,
95 LabelsAndEventClasses::ARMNN_PROFILING_EOL_EVENT_CLASS_NAME);
96 timelinePacket.SendTimelineEventClassBinaryPacket(LabelsAndEventClasses::ARMNN_PROFILING_EOL_EVENT_CLASS,
97 LabelsAndEventClasses::ARMNN_PROFILING_EOL_EVENT_CLASS_NAME_GUID);
98
99 timelinePacket.Commit();
100 }
101
CreateNamedTypedEntity(const std::string & name,const std::string & type)102 ProfilingDynamicGuid TimelineUtilityMethods::CreateNamedTypedEntity(const std::string& name, const std::string& type)
103 {
104 // Check that the entity name is valid
105 if (name.empty())
106 {
107 throw arm::pipe::InvalidArgumentException("Invalid entity name, the entity name cannot be empty");
108 }
109
110 // Check that the entity type is valid
111 if (type.empty())
112 {
113 throw arm::pipe::InvalidArgumentException("Invalid entity type, the entity type cannot be empty");
114 }
115
116 // Generate dynamic GUID of the entity
117 ProfilingDynamicGuid entityGuid = IProfilingService::GetNextGuid();
118
119 CreateNamedTypedEntity(entityGuid, name, type);
120
121 return entityGuid;
122 }
123
CreateNamedTypedEntity(ProfilingGuid entityGuid,const std::string & name,const std::string & type)124 void TimelineUtilityMethods::CreateNamedTypedEntity(ProfilingGuid entityGuid,
125 const std::string& name,
126 const std::string& type)
127 {
128 // Check that the entity name is valid
129 if (name.empty())
130 {
131 throw arm::pipe::InvalidArgumentException("Invalid entity name, the entity name cannot be empty");
132 }
133
134 // Check that the entity type is valid
135 if (type.empty())
136 {
137 throw arm::pipe::InvalidArgumentException("Invalid entity type, the entity type cannot be empty");
138 }
139
140 // Send Entity Binary Packet of the entity to the external profiling service
141 m_SendTimelinePacket->SendTimelineEntityBinaryPacket(entityGuid);
142
143 // Create name entity and send the relationship of the entity with the given name
144 NameEntity(entityGuid, name);
145
146 // Create type entity and send the relationship of the entity with the given type
147 TypeEntity(entityGuid, type);
148 }
149
CreateNamedTypedEntity(ProfilingGuid entityGuid,const std::string & name,ProfilingStaticGuid typeGuid)150 void TimelineUtilityMethods::CreateNamedTypedEntity(ProfilingGuid entityGuid,
151 const std::string& name,
152 ProfilingStaticGuid typeGuid)
153 {
154 // Check that the entity name is valid
155 if (name.empty())
156 {
157 throw arm::pipe::InvalidArgumentException("Invalid entity name, the entity name cannot be empty");
158 }
159
160 // Send Entity Binary Packet of the entity to the external profiling service
161 m_SendTimelinePacket->SendTimelineEntityBinaryPacket(entityGuid);
162
163 // Create name entity and send the relationship of the entity with the given name
164 NameEntity(entityGuid, name);
165
166 // Create type entity and send the relationship of the entity with the given type
167 MarkEntityWithType(entityGuid, typeGuid);
168 }
169
DeclareLabel(const std::string & labelName)170 ProfilingStaticGuid TimelineUtilityMethods::DeclareLabel(const std::string& labelName)
171 {
172 // Check that the label name is valid
173 if (labelName.empty())
174 {
175 // The label name is invalid
176 throw arm::pipe::InvalidArgumentException("Invalid label name, the label name cannot be empty");
177 }
178
179 // Generate a static GUID for the given label name
180 ProfilingStaticGuid labelGuid = IProfilingService::GetStaticId(labelName);
181
182 // Send the new label to the external profiling service, this call throws in case of error
183 m_SendTimelinePacket->SendTimelineLabelBinaryPacket(labelGuid, labelName);
184
185 return labelGuid;
186 }
187
MarkEntityWithLabel(ProfilingGuid entityGuid,const std::string & labelName,ProfilingStaticGuid labelTypeGuid)188 void TimelineUtilityMethods::MarkEntityWithLabel(ProfilingGuid entityGuid,
189 const std::string& labelName,
190 ProfilingStaticGuid labelTypeGuid)
191 {
192 // Check that the label name is valid
193 if (labelName.empty())
194 {
195 // The label name is invalid
196 throw arm::pipe::InvalidArgumentException("Invalid entity name, the entity name cannot be empty");
197 }
198
199 // Declare a label with the label's name, this call throws in case of error
200 ProfilingStaticGuid labelGuid = DeclareLabel(labelName);
201
202 // Generate a GUID for the label relationship
203 ProfilingDynamicGuid relationshipGuid = IProfilingService::GetNextGuid();
204
205 // Send the new label link to the external profiling service, this call throws in case of error
206 m_SendTimelinePacket->SendTimelineRelationshipBinaryPacket(ProfilingRelationshipType::LabelLink,
207 relationshipGuid,
208 entityGuid,
209 labelGuid,
210 labelTypeGuid);
211 }
212
MarkEntityWithType(ProfilingGuid entityGuid,ProfilingStaticGuid typeNameGuid)213 void TimelineUtilityMethods::MarkEntityWithType(ProfilingGuid entityGuid,
214 ProfilingStaticGuid typeNameGuid)
215 {
216 // Generate a GUID for the label relationship
217 ProfilingDynamicGuid relationshipGuid = IProfilingService::GetNextGuid();
218
219 // Send the new label link to the external profiling service, this call throws in case of error
220 m_SendTimelinePacket->SendTimelineRelationshipBinaryPacket(ProfilingRelationshipType::LabelLink,
221 relationshipGuid,
222 entityGuid,
223 typeNameGuid,
224 LabelsAndEventClasses::TYPE_GUID);
225 }
226
NameEntity(ProfilingGuid entityGuid,const std::string & name)227 void TimelineUtilityMethods::NameEntity(ProfilingGuid entityGuid, const std::string& name)
228 {
229 MarkEntityWithLabel(entityGuid, name, LabelsAndEventClasses::NAME_GUID);
230 }
231
TypeEntity(ProfilingGuid entityGuid,const std::string & type)232 void TimelineUtilityMethods::TypeEntity(ProfilingGuid entityGuid, const std::string& type)
233 {
234 MarkEntityWithLabel(entityGuid, type, LabelsAndEventClasses::TYPE_GUID);
235 }
236
CreateNamedTypedChildEntity(ProfilingGuid parentEntityGuid,const std::string & entityName,const std::string & entityType)237 ProfilingDynamicGuid TimelineUtilityMethods::CreateNamedTypedChildEntity(ProfilingGuid parentEntityGuid,
238 const std::string& entityName,
239 const std::string& entityType)
240 {
241 // Check that the entity name is valid
242 if (entityName.empty())
243 {
244 // The entity name is invalid
245 throw arm::pipe::InvalidArgumentException("Invalid entity name, the entity name cannot be empty");
246 }
247
248 // Check that the entity type is valid
249 if (entityType.empty())
250 {
251 // The entity type is invalid
252 throw arm::pipe::InvalidArgumentException("Invalid entity type, the entity type cannot be empty");
253 }
254
255 // Create a named type entity from the given name and type, this call throws in case of error
256 ProfilingDynamicGuid childEntityGuid = CreateNamedTypedEntity(entityName, entityType);
257
258 // Generate a GUID for the retention link relationship
259 ProfilingDynamicGuid retentionLinkGuid = IProfilingService::GetNextGuid();
260
261 // Send the new retention link to the external profiling service, this call throws in case of error
262 m_SendTimelinePacket->SendTimelineRelationshipBinaryPacket(ProfilingRelationshipType::RetentionLink,
263 retentionLinkGuid,
264 parentEntityGuid,
265 childEntityGuid,
266 LabelsAndEventClasses::EMPTY_GUID);
267
268 return childEntityGuid;
269 }
270
CreateNamedTypedChildEntity(ProfilingGuid childEntityGuid,ProfilingGuid parentEntityGuid,const std::string & entityName,const std::string & entityType)271 void TimelineUtilityMethods::CreateNamedTypedChildEntity(ProfilingGuid childEntityGuid,
272 ProfilingGuid parentEntityGuid,
273 const std::string& entityName,
274 const std::string& entityType)
275 {
276 // Check that the entity name is valid
277 if (entityName.empty())
278 {
279 // The entity name is invalid
280 throw arm::pipe::InvalidArgumentException("Invalid entity name, the entity name cannot be empty");
281 }
282
283 // Check that the entity type is valid
284 if (entityType.empty())
285 {
286 // The entity type is invalid
287 throw arm::pipe::InvalidArgumentException("Invalid entity type, the entity type cannot be empty");
288 }
289
290 // Create a named type entity from the given guid, name and type, this call throws in case of error
291 CreateNamedTypedEntity(childEntityGuid, entityName, entityType);
292
293 // Generate a GUID for the retention link relationship
294 ProfilingDynamicGuid retentionLinkGuid = IProfilingService::GetNextGuid();
295
296 // Send the new retention link to the external profiling service, this call throws in case of error
297 m_SendTimelinePacket->SendTimelineRelationshipBinaryPacket(ProfilingRelationshipType::RetentionLink,
298 retentionLinkGuid,
299 parentEntityGuid,
300 childEntityGuid,
301 LabelsAndEventClasses::CHILD_GUID);
302 }
303
CreateNamedTypedChildEntity(ProfilingGuid childEntityGuid,ProfilingGuid parentEntityGuid,const std::string & entityName,ProfilingStaticGuid typeGuid)304 void TimelineUtilityMethods::CreateNamedTypedChildEntity(ProfilingGuid childEntityGuid,
305 ProfilingGuid parentEntityGuid,
306 const std::string& entityName,
307 ProfilingStaticGuid typeGuid)
308 {
309 // Check that the entity name is valid
310 if (entityName.empty())
311 {
312 // The entity name is invalid
313 throw arm::pipe::InvalidArgumentException("Invalid entity name, the entity name cannot be empty");
314 }
315
316 // Create a named type entity from the given guid, name and type, this call throws in case of error
317 CreateNamedTypedEntity(childEntityGuid, entityName, typeGuid);
318
319 // Generate a GUID for the retention link relationship
320 ProfilingDynamicGuid retentionLinkGuid = IProfilingService::GetNextGuid();
321
322 // Send the new retention link to the external profiling service, this call throws in case of error
323 m_SendTimelinePacket->SendTimelineRelationshipBinaryPacket(ProfilingRelationshipType::RetentionLink,
324 retentionLinkGuid,
325 parentEntityGuid,
326 childEntityGuid,
327 LabelsAndEventClasses::CHILD_GUID);
328 }
329
CreateRelationship(ProfilingRelationshipType relationshipType,ProfilingGuid headGuid,ProfilingGuid tailGuid,ProfilingGuid relationshipCategory)330 ProfilingDynamicGuid TimelineUtilityMethods::CreateRelationship(ProfilingRelationshipType relationshipType,
331 ProfilingGuid headGuid,
332 ProfilingGuid tailGuid,
333 ProfilingGuid relationshipCategory)
334 {
335 // Generate a GUID for the relationship
336 ProfilingDynamicGuid relationshipGuid = IProfilingService::GetNextGuid();
337
338 // Send the new retention link to the external profiling service, this call throws in case of error
339 m_SendTimelinePacket->SendTimelineRelationshipBinaryPacket(relationshipType,
340 relationshipGuid,
341 headGuid,
342 tailGuid,
343 relationshipCategory);
344 return relationshipGuid;
345 }
346
CreateConnectionRelationship(ProfilingRelationshipType relationshipType,ProfilingGuid headGuid,ProfilingGuid tailGuid)347 ProfilingDynamicGuid TimelineUtilityMethods::CreateConnectionRelationship(ProfilingRelationshipType relationshipType,
348 ProfilingGuid headGuid,
349 ProfilingGuid tailGuid)
350 {
351 // Generate a GUID for the relationship
352 ProfilingDynamicGuid relationshipGuid = IProfilingService::GetNextGuid();
353
354 // Send the new retention link to the external profiling service, this call throws in case of error
355 m_SendTimelinePacket->SendTimelineRelationshipBinaryPacket(relationshipType,
356 relationshipGuid,
357 headGuid,
358 tailGuid,
359 LabelsAndEventClasses::CONNECTION_GUID);
360 return relationshipGuid;
361 }
362
CreateTypedEntity(ProfilingGuid entityGuid,ProfilingStaticGuid entityTypeGuid)363 void TimelineUtilityMethods::CreateTypedEntity(ProfilingGuid entityGuid, ProfilingStaticGuid entityTypeGuid)
364 {
365 // Send Entity Binary Packet of the entity to the external profiling service
366 m_SendTimelinePacket->SendTimelineEntityBinaryPacket(entityGuid);
367
368 // Create type entity and send the relationship of the entity with the given type
369 MarkEntityWithType(entityGuid, entityTypeGuid);
370 }
371
RecordEvent(ProfilingGuid entityGuid,ProfilingStaticGuid eventClassGuid)372 ProfilingDynamicGuid TimelineUtilityMethods::RecordEvent(ProfilingGuid entityGuid, ProfilingStaticGuid eventClassGuid)
373 {
374 // Take a timestamp
375 uint64_t timestamp = GetTimestamp();
376
377 // Get the thread id
378 int threadId = arm::pipe::GetCurrentThreadId();
379
380 // Generate a GUID for the event
381 ProfilingDynamicGuid eventGuid = IProfilingService::GetNextGuid();
382
383 // Send the new timeline event to the external profiling service, this call throws in case of error
384 m_SendTimelinePacket->SendTimelineEventBinaryPacket(timestamp, threadId, eventGuid);
385
386 // Generate a GUID for the execution link
387 ProfilingDynamicGuid executionLinkId = IProfilingService::GetNextGuid();
388
389 // Send the new execution link to the external profiling service, this call throws in case of error
390 m_SendTimelinePacket->SendTimelineRelationshipBinaryPacket(ProfilingRelationshipType::ExecutionLink,
391 executionLinkId,
392 entityGuid,
393 eventGuid,
394 eventClassGuid);
395
396 return eventGuid;
397 }
398
RecordWorkloadInferenceAndStartOfLifeEvent(ProfilingGuid workloadGuid,ProfilingGuid inferenceGuid)399 ProfilingDynamicGuid TimelineUtilityMethods::RecordWorkloadInferenceAndStartOfLifeEvent(ProfilingGuid workloadGuid,
400 ProfilingGuid inferenceGuid)
401 {
402 ProfilingDynamicGuid workloadInferenceGuid = IProfilingService::GetNextGuid();
403 CreateTypedEntity(workloadInferenceGuid, LabelsAndEventClasses::WORKLOAD_EXECUTION_GUID);
404 CreateRelationship(ProfilingRelationshipType::RetentionLink,
405 inferenceGuid,
406 workloadInferenceGuid,
407 LabelsAndEventClasses::CHILD_GUID);
408 CreateRelationship(ProfilingRelationshipType::RetentionLink,
409 workloadGuid,
410 workloadInferenceGuid,
411 LabelsAndEventClasses::EXECUTION_OF_GUID);
412 RecordEvent(workloadInferenceGuid, LabelsAndEventClasses::ARMNN_PROFILING_SOL_EVENT_CLASS);
413 return workloadInferenceGuid;
414 }
415
RecordEndOfLifeEvent(ProfilingGuid entityGuid)416 void TimelineUtilityMethods::RecordEndOfLifeEvent(ProfilingGuid entityGuid)
417 {
418 RecordEvent(entityGuid, LabelsAndEventClasses::ARMNN_PROFILING_EOL_EVENT_CLASS);
419 }
420
421 } // namespace pipe
422
423 } // namespace arm
424