1 // 2 // Copyright © 2019 Arm Ltd and Contributors. All rights reserved. 3 // SPDX-License-Identifier: MIT 4 // 5 6 #include "ProfilingMocks.hpp" 7 #include "ProfilingTestUtils.hpp" 8 9 #include <ArmNNProfilingServiceInitialiser.hpp> 10 11 #include <armnn/profiling/ArmNNProfiling.hpp> 12 13 #include <client/include/TimelineUtilityMethods.hpp> 14 15 #include <client/src/SendTimelinePacket.hpp> 16 #include <client/src/ProfilingService.hpp> 17 18 #include <common/include/LabelsAndEventClasses.hpp> 19 20 #include <memory> 21 22 #include <doctest/doctest.h> 23 24 using namespace armnn; 25 using namespace arm::pipe; 26 27 TEST_SUITE("TimelineUtilityMethodsTests") 28 { 29 TEST_CASE("CreateTypedLabelTest") 30 { 31 MockBufferManager mockBufferManager(1024); 32 armnn::ArmNNProfilingServiceInitialiser initialiser; 33 ProfilingService profilingService(arm::pipe::MAX_ARMNN_COUNTER, 34 initialiser, 35 arm::pipe::ARMNN_SOFTWARE_INFO, 36 arm::pipe::ARMNN_SOFTWARE_VERSION, 37 arm::pipe::ARMNN_HARDWARE_VERSION); 38 39 std::unique_ptr<ISendTimelinePacket> sendTimelinePacket = std::make_unique<SendTimelinePacket>(mockBufferManager); 40 TimelineUtilityMethods timelineUtilityMethods(sendTimelinePacket); 41 42 // Generate first guid to ensure that the named typed entity guid is not 0 on local single test. 43 profilingService.NextGuid(); 44 45 ProfilingGuid entityGuid(123); 46 const std::string entityName = "some entity"; 47 ProfilingStaticGuid labelTypeGuid(456); 48 49 CHECK_NOTHROW(timelineUtilityMethods.MarkEntityWithLabel(entityGuid, entityName, labelTypeGuid)); 50 51 // Commit all packets at once 52 timelineUtilityMethods.Commit(); 53 54 // Get the readable buffer 55 auto readableBuffer = mockBufferManager.GetReadableBuffer(); 56 CHECK(readableBuffer != nullptr); 57 unsigned int size = readableBuffer->GetSize(); 58 CHECK(size == 76); 59 const unsigned char* readableData = readableBuffer->GetReadableData(); 60 CHECK(readableData != nullptr); 61 62 // Utils 63 unsigned int offset = 0; 64 65 // Verify Header 66 VerifyTimelineHeaderBinary(readableData, offset, 68); 67 68 // First dataset sent: TimelineLabelBinaryPacket 69 VerifyTimelineLabelBinaryPacketData(arm::pipe::EmptyOptional(), entityName, readableData, offset); 70 71 // Second dataset sent: TimelineRelationshipBinaryPacket 72 VerifyTimelineRelationshipBinaryPacketData(ProfilingRelationshipType::LabelLink, 73 arm::pipe::EmptyOptional(), 74 entityGuid, 75 arm::pipe::EmptyOptional(), 76 labelTypeGuid, 77 readableData, 78 offset); 79 80 // Mark the buffer as read 81 mockBufferManager.MarkRead(readableBuffer); 82 } 83 84 TEST_CASE("SendWellKnownLabelsAndEventClassesTest") 85 { 86 MockBufferManager mockBufferManager(1024); 87 armnn::ArmNNProfilingServiceInitialiser initialiser; 88 ProfilingService profilingService(arm::pipe::MAX_ARMNN_COUNTER, 89 initialiser, 90 arm::pipe::ARMNN_SOFTWARE_INFO, 91 arm::pipe::ARMNN_SOFTWARE_VERSION, 92 arm::pipe::ARMNN_HARDWARE_VERSION); 93 SendTimelinePacket sendTimelinePacket(mockBufferManager); 94 95 CHECK_NOTHROW(TimelineUtilityMethods::SendWellKnownLabelsAndEventClasses(sendTimelinePacket)); 96 97 // Get the readable buffer 98 auto readableBuffer = mockBufferManager.GetReadableBuffer(); 99 CHECK(readableBuffer != nullptr); 100 unsigned int size = readableBuffer->GetSize(); 101 CHECK(size == 460); 102 const unsigned char* readableData = readableBuffer->GetReadableData(); 103 CHECK(readableData != nullptr); 104 105 // Utils 106 unsigned int offset = 0; 107 108 // Verify Header 109 VerifyTimelineHeaderBinary(readableData, offset, 452); 110 111 // First "well-known" label: NAME 112 VerifyTimelineLabelBinaryPacketData(LabelsAndEventClasses::NAME_GUID, 113 LabelsAndEventClasses::NAME_LABEL, 114 readableData, 115 offset); 116 117 // Second "well-known" label: TYPE 118 VerifyTimelineLabelBinaryPacketData(LabelsAndEventClasses::TYPE_GUID, 119 LabelsAndEventClasses::TYPE_LABEL, 120 readableData, 121 offset); 122 123 // Third "well-known" label: INDEX 124 VerifyTimelineLabelBinaryPacketData(LabelsAndEventClasses::INDEX_GUID, 125 LabelsAndEventClasses::INDEX_LABEL, 126 readableData, 127 offset); 128 129 // Forth "well-known" label: BACKENDID 130 VerifyTimelineLabelBinaryPacketData(LabelsAndEventClasses::BACKENDID_GUID, 131 LabelsAndEventClasses::BACKENDID_LABEL, 132 readableData, 133 offset); 134 135 // Fifth "well-known" label: CHILD 136 VerifyTimelineLabelBinaryPacketData(LabelsAndEventClasses::CHILD_GUID, 137 LabelsAndEventClasses::CHILD_LABEL, 138 readableData, 139 offset); 140 141 // Sixth "well-known" label: EXECUTION_OF 142 VerifyTimelineLabelBinaryPacketData(LabelsAndEventClasses::EXECUTION_OF_GUID, 143 LabelsAndEventClasses::EXECUTION_OF_LABEL, 144 readableData, 145 offset); 146 147 // Seventh "well-known" label: PROCESS_ID_LABEL 148 VerifyTimelineLabelBinaryPacketData(LabelsAndEventClasses::PROCESS_ID_GUID, 149 LabelsAndEventClasses::PROCESS_ID_LABEL, 150 readableData, 151 offset); 152 153 // Well-known types 154 // Layer 155 VerifyTimelineLabelBinaryPacketData(LabelsAndEventClasses::LAYER_GUID, 156 LabelsAndEventClasses::LAYER, 157 readableData, 158 offset); 159 160 // Workload 161 VerifyTimelineLabelBinaryPacketData(LabelsAndEventClasses::WORKLOAD_GUID, 162 LabelsAndEventClasses::WORKLOAD, 163 readableData, 164 offset); 165 166 // Network 167 VerifyTimelineLabelBinaryPacketData(LabelsAndEventClasses::NETWORK_GUID, 168 LabelsAndEventClasses::NETWORK, 169 readableData, 170 offset); 171 172 // Connection 173 VerifyTimelineLabelBinaryPacketData(LabelsAndEventClasses::CONNECTION_GUID, 174 LabelsAndEventClasses::CONNECTION, 175 readableData, 176 offset); 177 178 // Inference 179 VerifyTimelineLabelBinaryPacketData(LabelsAndEventClasses::INFERENCE_GUID, 180 LabelsAndEventClasses::INFERENCE, 181 readableData, 182 offset); 183 184 // Workload Execution 185 VerifyTimelineLabelBinaryPacketData(LabelsAndEventClasses::WORKLOAD_EXECUTION_GUID, 186 LabelsAndEventClasses::WORKLOAD_EXECUTION, 187 readableData, 188 offset); 189 190 // First "well-known" event class: START OF LIFE 191 VerifyTimelineLabelBinaryPacketData(LabelsAndEventClasses::ARMNN_PROFILING_SOL_EVENT_CLASS_NAME_GUID, 192 LabelsAndEventClasses::ARMNN_PROFILING_SOL_EVENT_CLASS_NAME, 193 readableData, 194 offset); 195 196 VerifyTimelineEventClassBinaryPacketData(LabelsAndEventClasses::ARMNN_PROFILING_SOL_EVENT_CLASS, 197 LabelsAndEventClasses::ARMNN_PROFILING_SOL_EVENT_CLASS_NAME_GUID, 198 readableData, 199 offset); 200 201 // Second "well-known" event class: END OF LIFE 202 VerifyTimelineLabelBinaryPacketData(LabelsAndEventClasses::ARMNN_PROFILING_EOL_EVENT_CLASS_NAME_GUID, 203 LabelsAndEventClasses::ARMNN_PROFILING_EOL_EVENT_CLASS_NAME, 204 readableData, 205 offset); 206 207 VerifyTimelineEventClassBinaryPacketData(LabelsAndEventClasses::ARMNN_PROFILING_EOL_EVENT_CLASS, 208 LabelsAndEventClasses::ARMNN_PROFILING_EOL_EVENT_CLASS_NAME_GUID, 209 readableData, 210 offset); 211 212 // Mark the buffer as read 213 mockBufferManager.MarkRead(readableBuffer); 214 } 215 216 TEST_CASE("CreateNamedTypedChildEntityTest") 217 { 218 MockBufferManager mockBufferManager(1024); 219 armnn::ArmNNProfilingServiceInitialiser initialiser; 220 ProfilingService profilingService(arm::pipe::MAX_ARMNN_COUNTER, 221 initialiser, 222 arm::pipe::ARMNN_SOFTWARE_INFO, 223 arm::pipe::ARMNN_SOFTWARE_VERSION, 224 arm::pipe::ARMNN_HARDWARE_VERSION); 225 std::unique_ptr<ISendTimelinePacket> sendTimelinePacket = std::make_unique<SendTimelinePacket>(mockBufferManager); 226 TimelineUtilityMethods timelineUtilityMethods(sendTimelinePacket); 227 228 ProfilingDynamicGuid childEntityGuid(0); 229 ProfilingGuid parentEntityGuid(123); 230 const std::string entityName = "some entity"; 231 const std::string entityType = "some type"; 232 233 // Generate first guid to ensure that the named typed entity guid is not 0 on local single test. 234 profilingService.NextGuid(); 235 236 CHECK_THROWS_AS(timelineUtilityMethods.CreateNamedTypedChildEntity(parentEntityGuid, "", entityType), 237 arm::pipe::InvalidArgumentException); 238 CHECK_THROWS_AS(timelineUtilityMethods.CreateNamedTypedChildEntity(parentEntityGuid, entityName, ""), 239 arm::pipe::InvalidArgumentException); 240 CHECK_THROWS_AS(timelineUtilityMethods.CreateNamedTypedChildEntity( 241 childEntityGuid, parentEntityGuid, "", entityType), arm::pipe::InvalidArgumentException); 242 CHECK_THROWS_AS(timelineUtilityMethods.CreateNamedTypedChildEntity( 243 childEntityGuid, parentEntityGuid, entityName, ""), arm::pipe::InvalidArgumentException); 244 245 CHECK_NOTHROW(childEntityGuid = timelineUtilityMethods.CreateNamedTypedChildEntity(parentEntityGuid, 246 entityName, 247 entityType)); 248 CHECK(childEntityGuid != ProfilingGuid(0)); 249 250 // Commit all packets at onceTimelineUtilityMethodsTests.cpp 251 timelineUtilityMethods.Commit(); 252 253 // Get the readable buffer 254 auto readableBuffer = mockBufferManager.GetReadableBuffer(); 255 CHECK(readableBuffer != nullptr); 256 unsigned int size = readableBuffer->GetSize(); 257 CHECK(size == 196); 258 const unsigned char* readableData = readableBuffer->GetReadableData(); 259 CHECK(readableData != nullptr); 260 261 // Utils 262 unsigned int offset = 0; 263 264 // Verify Header 265 VerifyTimelineHeaderBinary(readableData, offset, 188); 266 267 // First dataset sent: TimelineEntityBinaryPacket 268 VerifyTimelineEntityBinaryPacketData(arm::pipe::EmptyOptional(), readableData, offset); 269 270 // Second dataset sent: TimelineLabelBinaryPacket 271 VerifyTimelineLabelBinaryPacketData(arm::pipe::EmptyOptional(), entityName, readableData, offset); 272 273 // Third dataset sent: TimelineRelationshipBinaryPacket 274 VerifyTimelineRelationshipBinaryPacketData(ProfilingRelationshipType::LabelLink, 275 arm::pipe::EmptyOptional(), 276 arm::pipe::EmptyOptional(), 277 arm::pipe::EmptyOptional(), 278 LabelsAndEventClasses::NAME_GUID, 279 readableData, 280 offset); 281 282 // Fifth dataset sent: TimelineLabelBinaryPacket 283 VerifyTimelineLabelBinaryPacketData(arm::pipe::EmptyOptional(), entityType, readableData, offset); 284 285 // Sixth dataset sent: TimelineRelationshipBinaryPacket 286 VerifyTimelineRelationshipBinaryPacketData(ProfilingRelationshipType::LabelLink, 287 arm::pipe::EmptyOptional(), 288 arm::pipe::EmptyOptional(), 289 arm::pipe::EmptyOptional(), 290 LabelsAndEventClasses::TYPE_GUID, 291 readableData, 292 offset); 293 294 295 // Eighth dataset sent: TimelineRelationshipBinaryPacket 296 VerifyTimelineRelationshipBinaryPacketData(ProfilingRelationshipType::RetentionLink, 297 arm::pipe::EmptyOptional(), 298 parentEntityGuid, 299 arm::pipe::EmptyOptional(), 300 arm::pipe::EmptyOptional(), 301 readableData, 302 offset); 303 304 // Mark the buffer as read 305 mockBufferManager.MarkRead(readableBuffer); 306 } 307 308 TEST_CASE("DeclareLabelTest") 309 { 310 MockBufferManager mockBufferManager(1024); 311 armnn::ArmNNProfilingServiceInitialiser initialiser; 312 ProfilingService profilingService(arm::pipe::MAX_ARMNN_COUNTER, 313 initialiser, 314 arm::pipe::ARMNN_SOFTWARE_INFO, 315 arm::pipe::ARMNN_SOFTWARE_VERSION, 316 arm::pipe::ARMNN_HARDWARE_VERSION); 317 std::unique_ptr<ISendTimelinePacket> sendTimelinePacket = std::make_unique<SendTimelinePacket>(mockBufferManager); 318 TimelineUtilityMethods timelineUtilityMethods(sendTimelinePacket); 319 320 // Generate first guid to ensure that the named typed entity guid is not 0 on local single test. 321 profilingService.NextGuid(); 322 323 // Try declaring an invalid (empty) label 324 CHECK_THROWS_AS(timelineUtilityMethods.DeclareLabel(""), arm::pipe::InvalidArgumentException); 325 326 // Try declaring an invalid (wrong SWTrace format) label 327 CHECK_THROWS_AS(timelineUtilityMethods.DeclareLabel("inv@lid lab€l"), arm::pipe::ProfilingException); 328 329 // Declare a valid label 330 const std::string labelName = "valid label"; 331 ProfilingGuid labelGuid = 0; 332 CHECK_NOTHROW(labelGuid = timelineUtilityMethods.DeclareLabel(labelName)); 333 CHECK(labelGuid != ProfilingGuid(0)); 334 335 // Try adding the same label as before 336 ProfilingGuid newLabelGuid = 0; 337 CHECK_NOTHROW(newLabelGuid = timelineUtilityMethods.DeclareLabel(labelName)); 338 CHECK(newLabelGuid != ProfilingGuid(0)); 339 CHECK(newLabelGuid == labelGuid); 340 } 341 342 TEST_CASE("CreateNameTypeEntityInvalidTest") 343 { 344 MockBufferManager mockBufferManager(1024); 345 armnn::ArmNNProfilingServiceInitialiser initialiser; 346 ProfilingService profilingService(arm::pipe::MAX_ARMNN_COUNTER, 347 initialiser, 348 arm::pipe::ARMNN_SOFTWARE_INFO, 349 arm::pipe::ARMNN_SOFTWARE_VERSION, 350 arm::pipe::ARMNN_HARDWARE_VERSION); 351 std::unique_ptr<ISendTimelinePacket> sendTimelinePacket = std::make_unique<SendTimelinePacket>(mockBufferManager); 352 TimelineUtilityMethods timelineUtilityMethods(sendTimelinePacket); 353 354 // Invalid name 355 CHECK_THROWS_AS(timelineUtilityMethods.CreateNamedTypedEntity("", "Type"), arm::pipe::InvalidArgumentException); 356 357 // Invalid type 358 CHECK_THROWS_AS(timelineUtilityMethods.CreateNamedTypedEntity("Name", ""), arm::pipe::InvalidArgumentException); 359 360 ProfilingDynamicGuid guid = profilingService.NextGuid(); 361 362 // CreatedNamedTypedEntity with Guid - Invalid name 363 CHECK_THROWS_AS(timelineUtilityMethods.CreateNamedTypedEntity(guid, "", "Type"), 364 arm::pipe::InvalidArgumentException); 365 366 // CreatedNamedTypedEntity with Guid - Invalid type 367 CHECK_THROWS_AS(timelineUtilityMethods.CreateNamedTypedEntity(guid, "Name", ""), 368 arm::pipe::InvalidArgumentException); 369 370 } 371 372 TEST_CASE("CreateNameTypeEntityTest") 373 { 374 MockBufferManager mockBufferManager(1024); 375 armnn::ArmNNProfilingServiceInitialiser initialiser; 376 ProfilingService profilingService(arm::pipe::MAX_ARMNN_COUNTER, 377 initialiser, 378 arm::pipe::ARMNN_SOFTWARE_INFO, 379 arm::pipe::ARMNN_SOFTWARE_VERSION, 380 arm::pipe::ARMNN_HARDWARE_VERSION); 381 std::unique_ptr<ISendTimelinePacket> sendTimelinePacket = std::make_unique<SendTimelinePacket>(mockBufferManager); 382 TimelineUtilityMethods timelineUtilityMethods(sendTimelinePacket); 383 384 const std::string entityName = "Entity0"; 385 const std::string entityType = "Type0"; 386 387 // Generate first guid to ensure that the named typed entity guid is not 0 on local single test. 388 profilingService.NextGuid(); 389 390 ProfilingDynamicGuid guid = timelineUtilityMethods.CreateNamedTypedEntity(entityName, entityType); 391 CHECK(guid != ProfilingGuid(0)); 392 393 // Commit all packets at once 394 timelineUtilityMethods.Commit(); 395 396 // Get the readable buffer 397 auto readableBuffer = mockBufferManager.GetReadableBuffer(); 398 CHECK(readableBuffer != nullptr); 399 unsigned int size = readableBuffer->GetSize(); 400 CHECK(size == 148); 401 const unsigned char* readableData = readableBuffer->GetReadableData(); 402 CHECK(readableData != nullptr); 403 404 // Utils 405 unsigned int offset = 0; 406 407 // Verify Header 408 VerifyTimelineHeaderBinary(readableData, offset, 140); 409 410 // First dataset sent: TimelineEntityBinaryPacket 411 VerifyTimelineEntityBinaryPacketData(guid, readableData, offset); 412 413 // Packets for Name Entity 414 // First dataset sent: TimelineLabelBinaryPacket 415 VerifyTimelineLabelBinaryPacketData(arm::pipe::EmptyOptional(), entityName, readableData, offset); 416 417 // Second dataset sent: TimelineRelationshipBinaryPacket 418 VerifyTimelineRelationshipBinaryPacketData(ProfilingRelationshipType::LabelLink, 419 arm::pipe::EmptyOptional(), 420 arm::pipe::EmptyOptional(), 421 arm::pipe::EmptyOptional(), 422 LabelsAndEventClasses::NAME_GUID, 423 readableData, 424 offset); 425 426 // Packets for Type Entity 427 // First dataset sent: TimelineLabelBinaryPacket 428 VerifyTimelineLabelBinaryPacketData(arm::pipe::EmptyOptional(), entityType, readableData, offset); 429 430 // Second dataset sent: TimelineRelationshipBinaryPacket 431 VerifyTimelineRelationshipBinaryPacketData(ProfilingRelationshipType::LabelLink, 432 arm::pipe::EmptyOptional(), 433 arm::pipe::EmptyOptional(), 434 arm::pipe::EmptyOptional(), 435 LabelsAndEventClasses::TYPE_GUID, 436 readableData, 437 offset); 438 439 440 // Mark the buffer as read 441 mockBufferManager.MarkRead(readableBuffer); 442 } 443 444 TEST_CASE("RecordEventTest") 445 { 446 MockBufferManager mockBufferManager(1024); 447 armnn::ArmNNProfilingServiceInitialiser initialiser; 448 ProfilingService profilingService(arm::pipe::MAX_ARMNN_COUNTER, 449 initialiser, 450 arm::pipe::ARMNN_SOFTWARE_INFO, 451 arm::pipe::ARMNN_SOFTWARE_VERSION, 452 arm::pipe::ARMNN_HARDWARE_VERSION); 453 std::unique_ptr<ISendTimelinePacket> sendTimelinePacket = std::make_unique<SendTimelinePacket>(mockBufferManager); 454 TimelineUtilityMethods timelineUtilityMethods(sendTimelinePacket); 455 // Generate first guid to ensure that the named typed entity guid is not 0 on local single test. 456 profilingService.NextGuid(); 457 458 ProfilingGuid entityGuid(123); 459 ProfilingStaticGuid eventClassGuid(456); 460 ProfilingDynamicGuid eventGuid(0); 461 CHECK_NOTHROW(eventGuid = timelineUtilityMethods.RecordEvent(entityGuid, eventClassGuid)); 462 CHECK(eventGuid != ProfilingGuid(0)); 463 464 // Commit all packets at once 465 timelineUtilityMethods.Commit(); 466 467 // Get the readable buffer 468 auto readableBuffer = mockBufferManager.GetReadableBuffer(); 469 CHECK(readableBuffer != nullptr); 470 unsigned int size = readableBuffer->GetSize(); 471 472 CHECK(size == 68 + ThreadIdSize); 473 474 const unsigned char* readableData = readableBuffer->GetReadableData(); 475 CHECK(readableData != nullptr); 476 477 // Utils 478 unsigned int offset = 0; 479 480 // Verify Header 481 VerifyTimelineHeaderBinary(readableData, offset, 60 + ThreadIdSize); 482 483 // First dataset sent: TimelineEntityBinaryPacket 484 VerifyTimelineEventBinaryPacket( 485 arm::pipe::EmptyOptional(), arm::pipe::EmptyOptional(), arm::pipe::EmptyOptional(), readableData, offset); 486 487 // Second dataset sent: TimelineRelationshipBinaryPacket 488 VerifyTimelineRelationshipBinaryPacketData(ProfilingRelationshipType::ExecutionLink, 489 arm::pipe::EmptyOptional(), 490 entityGuid, 491 eventGuid, 492 eventClassGuid, 493 readableData, 494 offset); 495 496 // Mark the buffer as read 497 mockBufferManager.MarkRead(readableBuffer); 498 } 499 500 } 501