From 24e8f9209249c9d41e57748a1b9d2f5f978db4ee Mon Sep 17 00:00:00 2001 From: Matteo Martincigh Date: Thu, 19 Sep 2019 11:57:46 +0100 Subject: IVGCVSW-3905 Create a first implementation of the send thread * Added the send thread directly to the SendCounterPacket class * Updated the SendCounterPacket class constructor to also take a reference of a IProfilingConnection object, used to send packets out * Added Start and Stop methods to SendCounterPacket to start and stop the send thread * Added mutex and wait condition to make the send thread waiting for something to send * This implementation used the old IBufferWrapper interface * Added defult (empty) constructor for the Packet class * Refactoring of IPeriodicCounterCapture and SocketProfilingConnection * Modified WritePacket to make it match IBufferWrapper::GetReadBuffer * Added unit test for regular and stress testing of the send thread Signed-off-by: Matteo Martincigh Change-Id: I8175619ff4e65c0d5be99bcd8bd9d8dd87f717c6 --- src/profiling/test/ProfilingTests.cpp | 15 +- src/profiling/test/SendCounterPacketTests.cpp | 438 ++++++++++++++++++++++++-- src/profiling/test/SendCounterPacketTests.hpp | 157 ++++++++- 3 files changed, 563 insertions(+), 47 deletions(-) (limited to 'src/profiling/test') diff --git a/src/profiling/test/ProfilingTests.cpp b/src/profiling/test/ProfilingTests.cpp index b90d469424..1741160f96 100644 --- a/src/profiling/test/ProfilingTests.cpp +++ b/src/profiling/test/ProfilingTests.cpp @@ -36,6 +36,7 @@ #include #include #include +#include BOOST_AUTO_TEST_SUITE(ExternalProfiling) @@ -101,7 +102,7 @@ public: void Close(){} - bool WritePacket(const char* buffer, uint32_t length) + bool WritePacket(const unsigned char* buffer, uint32_t length) { return false; } @@ -1754,8 +1755,9 @@ BOOST_AUTO_TEST_CASE(CounterSelectionCommandHandlerParseData) uint32_t version = 1; Holder holder; TestCaptureThread captureThread; + MockProfilingConnection mockProfilingConnection; MockBuffer mockBuffer(512); - SendCounterPacket sendCounterPacket(mockBuffer); + SendCounterPacket sendCounterPacket(mockProfilingConnection, mockBuffer); uint32_t sizeOfUint32 = numeric_cast(sizeof(uint32_t)); uint32_t sizeOfUint16 = numeric_cast(sizeof(uint16_t)); @@ -2112,8 +2114,9 @@ BOOST_AUTO_TEST_CASE(CheckPeriodicCounterCaptureThread) std::vector captureIds1 = { 0, 1 }; std::vector captureIds2; + MockProfilingConnection mockProfilingConnection; MockBuffer mockBuffer(512); - SendCounterPacket sendCounterPacket(mockBuffer); + SendCounterPacket sendCounterPacket(mockProfilingConnection, mockBuffer); std::vector counterIds; CaptureReader captureReader; @@ -2183,8 +2186,9 @@ BOOST_AUTO_TEST_CASE(RequestCounterDirectoryCommandHandlerTest0) Packet packetA(packetId, 0, packetData); + MockProfilingConnection mockProfilingConnection; MockBuffer mockBuffer(1024); - SendCounterPacket sendCounterPacket(mockBuffer); + SendCounterPacket sendCounterPacket(mockProfilingConnection, mockBuffer); CounterDirectory counterDirectory; @@ -2217,8 +2221,9 @@ BOOST_AUTO_TEST_CASE(RequestCounterDirectoryCommandHandlerTest1) Packet packetA(packetId, 0, packetData); + MockProfilingConnection mockProfilingConnection; MockBuffer mockBuffer(1024); - SendCounterPacket sendCounterPacket(mockBuffer); + SendCounterPacket sendCounterPacket(mockProfilingConnection, mockBuffer); CounterDirectory counterDirectory; const Device* device = counterDirectory.RegisterDevice("deviceA", 1); diff --git a/src/profiling/test/SendCounterPacketTests.cpp b/src/profiling/test/SendCounterPacketTests.cpp index 90bc9225a0..3dda2e7b37 100644 --- a/src/profiling/test/SendCounterPacketTests.cpp +++ b/src/profiling/test/SendCounterPacketTests.cpp @@ -8,6 +8,7 @@ #include #include #include +#include #include #include @@ -16,10 +17,22 @@ #include #include -#include using namespace armnn::profiling; +size_t GetDataLength(const MockStreamCounterBuffer& mockStreamCounterBuffer, size_t packetOffset) +{ + // The data length is the written in the second byte + return ReadUint32(mockStreamCounterBuffer.GetBuffer(), + boost::numeric_cast(packetOffset + sizeof(uint32_t))); +} + +size_t GetPacketSize(const MockStreamCounterBuffer& mockStreamCounterBuffer, size_t packetOffset) +{ + // The packet size is the data length plus the size of the packet header (always two words big) + return GetDataLength(mockStreamCounterBuffer, packetOffset) + 2 * sizeof(uint32_t); +} + BOOST_AUTO_TEST_SUITE(SendCounterPacketTests) BOOST_AUTO_TEST_CASE(MockSendCounterPacketTest) @@ -56,17 +69,18 @@ BOOST_AUTO_TEST_CASE(MockSendCounterPacketTest) BOOST_AUTO_TEST_CASE(SendPeriodicCounterSelectionPacketTest) { // Error no space left in buffer + MockProfilingConnection mockProfilingConnection; MockBuffer mockBuffer1(10); - SendCounterPacket sendPacket1(mockBuffer1); + SendCounterPacket sendPacket1(mockProfilingConnection, mockBuffer1); uint32_t capturePeriod = 1000; std::vector selectedCounterIds; BOOST_CHECK_THROW(sendPacket1.SendPeriodicCounterSelectionPacket(capturePeriod, selectedCounterIds), - armnn::profiling::BufferExhaustion); + BufferExhaustion); // Packet without any counters MockBuffer mockBuffer2(512); - SendCounterPacket sendPacket2(mockBuffer2); + SendCounterPacket sendPacket2(mockProfilingConnection, mockBuffer2); sendPacket2.SendPeriodicCounterSelectionPacket(capturePeriod, selectedCounterIds); unsigned int sizeRead = 0; @@ -83,7 +97,7 @@ BOOST_AUTO_TEST_CASE(SendPeriodicCounterSelectionPacketTest) // Full packet message MockBuffer mockBuffer3(512); - SendCounterPacket sendPacket3(mockBuffer3); + SendCounterPacket sendPacket3(mockProfilingConnection, mockBuffer3); selectedCounterIds.reserve(5); selectedCounterIds.emplace_back(100); @@ -119,8 +133,9 @@ BOOST_AUTO_TEST_CASE(SendPeriodicCounterSelectionPacketTest) BOOST_AUTO_TEST_CASE(SendPeriodicCounterCapturePacketTest) { // Error no space left in buffer + MockProfilingConnection mockProfilingConnection; MockBuffer mockBuffer1(10); - SendCounterPacket sendPacket1(mockBuffer1); + SendCounterPacket sendPacket1(mockProfilingConnection, mockBuffer1); auto captureTimestamp = std::chrono::steady_clock::now(); uint64_t time = static_cast(captureTimestamp.time_since_epoch().count()); @@ -131,7 +146,7 @@ BOOST_AUTO_TEST_CASE(SendPeriodicCounterCapturePacketTest) // Packet without any counters MockBuffer mockBuffer2(512); - SendCounterPacket sendPacket2(mockBuffer2); + SendCounterPacket sendPacket2(mockProfilingConnection, mockBuffer2); sendPacket2.SendPeriodicCounterCapturePacket(time, indexValuePairs); unsigned int sizeRead = 0; @@ -149,7 +164,7 @@ BOOST_AUTO_TEST_CASE(SendPeriodicCounterCapturePacketTest) // Full packet message MockBuffer mockBuffer3(512); - SendCounterPacket sendPacket3(mockBuffer3); + SendCounterPacket sendPacket3(mockProfilingConnection, mockBuffer3); indexValuePairs.reserve(5); indexValuePairs.emplace_back(std::make_pair(0, 100)); @@ -200,8 +215,9 @@ BOOST_AUTO_TEST_CASE(SendStreamMetaDataPacketTest) uint32_t sizeUint32 = numeric_cast(sizeof(uint32_t)); // Error no space left in buffer + MockProfilingConnection mockProfilingConnection; MockBuffer mockBuffer1(10); - SendCounterPacket sendPacket1(mockBuffer1); + SendCounterPacket sendPacket1(mockProfilingConnection, mockBuffer1); BOOST_CHECK_THROW(sendPacket1.SendStreamMetaDataPacket(), armnn::profiling::BufferExhaustion); // Full metadata packet @@ -220,7 +236,7 @@ BOOST_AUTO_TEST_CASE(SendStreamMetaDataPacketTest) uint32_t packetEntries = 6; MockBuffer mockBuffer2(512); - SendCounterPacket sendPacket2(mockBuffer2); + SendCounterPacket sendPacket2(mockProfilingConnection, mockBuffer2); sendPacket2.SendStreamMetaDataPacket(); unsigned int sizeRead = 0; const unsigned char* readBuffer2 = mockBuffer2.GetReadBuffer(sizeRead); @@ -313,8 +329,9 @@ BOOST_AUTO_TEST_CASE(SendStreamMetaDataPacketTest) BOOST_AUTO_TEST_CASE(CreateDeviceRecordTest) { + MockProfilingConnection mockProfilingConnection; MockBuffer mockBuffer(0); - SendCounterPacketTest sendCounterPacketTest(mockBuffer); + SendCounterPacketTest sendCounterPacketTest(mockProfilingConnection, mockBuffer); // Create a device for testing uint16_t deviceUid = 27; @@ -345,8 +362,9 @@ BOOST_AUTO_TEST_CASE(CreateDeviceRecordTest) BOOST_AUTO_TEST_CASE(CreateInvalidDeviceRecordTest) { + MockProfilingConnection mockProfilingConnection; MockBuffer mockBuffer(0); - SendCounterPacketTest sendCounterPacketTest(mockBuffer); + SendCounterPacketTest sendCounterPacketTest(mockProfilingConnection, mockBuffer); // Create a device for testing uint16_t deviceUid = 27; @@ -366,8 +384,9 @@ BOOST_AUTO_TEST_CASE(CreateInvalidDeviceRecordTest) BOOST_AUTO_TEST_CASE(CreateCounterSetRecordTest) { + MockProfilingConnection mockProfilingConnection; MockBuffer mockBuffer(0); - SendCounterPacketTest sendCounterPacketTest(mockBuffer); + SendCounterPacketTest sendCounterPacketTest(mockProfilingConnection, mockBuffer); // Create a counter set for testing uint16_t counterSetUid = 27; @@ -398,8 +417,9 @@ BOOST_AUTO_TEST_CASE(CreateCounterSetRecordTest) BOOST_AUTO_TEST_CASE(CreateInvalidCounterSetRecordTest) { + MockProfilingConnection mockProfilingConnection; MockBuffer mockBuffer(0); - SendCounterPacketTest sendCounterPacketTest(mockBuffer); + SendCounterPacketTest sendCounterPacketTest(mockProfilingConnection, mockBuffer); // Create a counter set for testing uint16_t counterSetUid = 27; @@ -419,8 +439,9 @@ BOOST_AUTO_TEST_CASE(CreateInvalidCounterSetRecordTest) BOOST_AUTO_TEST_CASE(CreateEventRecordTest) { + MockProfilingConnection mockProfilingConnection; MockBuffer mockBuffer(0); - SendCounterPacketTest sendCounterPacketTest(mockBuffer); + SendCounterPacketTest sendCounterPacketTest(mockProfilingConnection, mockBuffer); // Create a counter for testing uint16_t counterUid = 7256; @@ -539,8 +560,9 @@ BOOST_AUTO_TEST_CASE(CreateEventRecordTest) BOOST_AUTO_TEST_CASE(CreateEventRecordNoUnitsTest) { + MockProfilingConnection mockProfilingConnection; MockBuffer mockBuffer(0); - SendCounterPacketTest sendCounterPacketTest(mockBuffer); + SendCounterPacketTest sendCounterPacketTest(mockProfilingConnection, mockBuffer); // Create a counter for testing uint16_t counterUid = 44312; @@ -642,8 +664,9 @@ BOOST_AUTO_TEST_CASE(CreateEventRecordNoUnitsTest) BOOST_AUTO_TEST_CASE(CreateInvalidEventRecordTest1) { + MockProfilingConnection mockProfilingConnection; MockBuffer mockBuffer(0); - SendCounterPacketTest sendCounterPacketTest(mockBuffer); + SendCounterPacketTest sendCounterPacketTest(mockProfilingConnection, mockBuffer); // Create a counter for testing uint16_t counterUid = 7256; @@ -680,8 +703,9 @@ BOOST_AUTO_TEST_CASE(CreateInvalidEventRecordTest1) BOOST_AUTO_TEST_CASE(CreateInvalidEventRecordTest2) { + MockProfilingConnection mockProfilingConnection; MockBuffer mockBuffer(0); - SendCounterPacketTest sendCounterPacketTest(mockBuffer); + SendCounterPacketTest sendCounterPacketTest(mockProfilingConnection, mockBuffer); // Create a counter for testing uint16_t counterUid = 7256; @@ -718,8 +742,9 @@ BOOST_AUTO_TEST_CASE(CreateInvalidEventRecordTest2) BOOST_AUTO_TEST_CASE(CreateInvalidEventRecordTest3) { + MockProfilingConnection mockProfilingConnection; MockBuffer mockBuffer(0); - SendCounterPacketTest sendCounterPacketTest(mockBuffer); + SendCounterPacketTest sendCounterPacketTest(mockProfilingConnection, mockBuffer); // Create a counter for testing uint16_t counterUid = 7256; @@ -756,8 +781,9 @@ BOOST_AUTO_TEST_CASE(CreateInvalidEventRecordTest3) BOOST_AUTO_TEST_CASE(CreateCategoryRecordTest) { + MockProfilingConnection mockProfilingConnection; MockBuffer mockBuffer(0); - SendCounterPacketTest sendCounterPacketTest(mockBuffer); + SendCounterPacketTest sendCounterPacketTest(mockProfilingConnection, mockBuffer); // Create a category for testing const std::string categoryName = "some_category"; @@ -957,8 +983,9 @@ BOOST_AUTO_TEST_CASE(CreateCategoryRecordTest) BOOST_AUTO_TEST_CASE(CreateInvalidCategoryRecordTest1) { + MockProfilingConnection mockProfilingConnection; MockBuffer mockBuffer(0); - SendCounterPacketTest sendCounterPacketTest(mockBuffer); + SendCounterPacketTest sendCounterPacketTest(mockProfilingConnection, mockBuffer); // Create a category for testing const std::string categoryName = "some invalid category"; @@ -980,8 +1007,9 @@ BOOST_AUTO_TEST_CASE(CreateInvalidCategoryRecordTest1) BOOST_AUTO_TEST_CASE(CreateInvalidCategoryRecordTest2) { + MockProfilingConnection mockProfilingConnection; MockBuffer mockBuffer(0); - SendCounterPacketTest sendCounterPacketTest(mockBuffer); + SendCounterPacketTest sendCounterPacketTest(mockProfilingConnection, mockBuffer); // Create a category for testing const std::string categoryName = "some_category"; @@ -1038,8 +1066,9 @@ BOOST_AUTO_TEST_CASE(SendCounterDirectoryPacketTest1) BOOST_CHECK(device2); // Buffer with not enough space + MockProfilingConnection mockProfilingConnection; MockBuffer mockBuffer(10); - SendCounterPacket sendCounterPacket(mockBuffer); + SendCounterPacket sendCounterPacket(mockProfilingConnection, mockBuffer); BOOST_CHECK_THROW(sendCounterPacket.SendCounterDirectoryPacket(counterDirectory), armnn::profiling::BufferExhaustion); } @@ -1130,8 +1159,9 @@ BOOST_AUTO_TEST_CASE(SendCounterDirectoryPacketTest2) BOOST_CHECK(counter3); // Buffer with enough space + MockProfilingConnection mockProfilingConnection; MockBuffer mockBuffer(1024); - SendCounterPacket sendCounterPacket(mockBuffer); + SendCounterPacket sendCounterPacket(mockProfilingConnection, mockBuffer); BOOST_CHECK_NO_THROW(sendCounterPacket.SendCounterDirectoryPacket(counterDirectory)); // Get the read buffer @@ -1529,8 +1559,9 @@ BOOST_AUTO_TEST_CASE(SendCounterDirectoryPacketTest3) BOOST_CHECK(device); // Buffer with enough space + MockProfilingConnection mockProfilingConnection; MockBuffer mockBuffer(1024); - SendCounterPacket sendCounterPacket(mockBuffer); + SendCounterPacket sendCounterPacket(mockProfilingConnection, mockBuffer); BOOST_CHECK_THROW(sendCounterPacket.SendCounterDirectoryPacket(counterDirectory), armnn::RuntimeException); } @@ -1547,8 +1578,9 @@ BOOST_AUTO_TEST_CASE(SendCounterDirectoryPacketTest4) BOOST_CHECK(counterSet); // Buffer with enough space + MockProfilingConnection mockProfilingConnection; MockBuffer mockBuffer(1024); - SendCounterPacket sendCounterPacket(mockBuffer); + SendCounterPacket sendCounterPacket(mockProfilingConnection, mockBuffer); BOOST_CHECK_THROW(sendCounterPacket.SendCounterDirectoryPacket(counterDirectory), armnn::RuntimeException); } @@ -1565,8 +1597,9 @@ BOOST_AUTO_TEST_CASE(SendCounterDirectoryPacketTest5) BOOST_CHECK(category); // Buffer with enough space + MockProfilingConnection mockProfilingConnection; MockBuffer mockBuffer(1024); - SendCounterPacket sendCounterPacket(mockBuffer); + SendCounterPacket sendCounterPacket(mockProfilingConnection, mockBuffer); BOOST_CHECK_THROW(sendCounterPacket.SendCounterDirectoryPacket(counterDirectory), armnn::RuntimeException); } @@ -1599,8 +1632,9 @@ BOOST_AUTO_TEST_CASE(SendCounterDirectoryPacketTest6) BOOST_CHECK(category); // Buffer with enough space + MockProfilingConnection mockProfilingConnection; MockBuffer mockBuffer(1024); - SendCounterPacket sendCounterPacket(mockBuffer); + SendCounterPacket sendCounterPacket(mockProfilingConnection, mockBuffer); BOOST_CHECK_THROW(sendCounterPacket.SendCounterDirectoryPacket(counterDirectory), armnn::RuntimeException); } @@ -1648,9 +1682,355 @@ BOOST_AUTO_TEST_CASE(SendCounterDirectoryPacketTest7) BOOST_CHECK(counter); // Buffer with enough space + MockProfilingConnection mockProfilingConnection; MockBuffer mockBuffer(1024); - SendCounterPacket sendCounterPacket(mockBuffer); + SendCounterPacket sendCounterPacket(mockProfilingConnection, mockBuffer); BOOST_CHECK_THROW(sendCounterPacket.SendCounterDirectoryPacket(counterDirectory), armnn::RuntimeException); } +BOOST_AUTO_TEST_CASE(SendThreadTest0) +{ + MockProfilingConnection mockProfilingConnection; + MockStreamCounterBuffer mockStreamCounterBuffer(0); + SendCounterPacket sendCounterPacket(mockProfilingConnection, mockStreamCounterBuffer); + + // Try to start the send thread many times, it must only start once + + sendCounterPacket.Start(); + BOOST_CHECK(sendCounterPacket.IsRunning()); + sendCounterPacket.Start(); + sendCounterPacket.Start(); + sendCounterPacket.Start(); + sendCounterPacket.Start(); + BOOST_CHECK(sendCounterPacket.IsRunning()); + + std::this_thread::sleep_for(std::chrono::seconds(1)); + + sendCounterPacket.Stop(); + BOOST_CHECK(!sendCounterPacket.IsRunning()); +} + +BOOST_AUTO_TEST_CASE(SendThreadTest1) +{ + size_t totalWrittenSize = 0; + + MockProfilingConnection mockProfilingConnection; + MockStreamCounterBuffer mockStreamCounterBuffer(100); + SendCounterPacket sendCounterPacket(mockProfilingConnection, mockStreamCounterBuffer); + sendCounterPacket.Start(); + + // Interleaving writes and reads to/from the buffer with pauses to test that the send thread actually waits for + // something to become available for reading + + std::this_thread::sleep_for(std::chrono::seconds(1)); + + CounterDirectory counterDirectory; + sendCounterPacket.SendStreamMetaDataPacket(); + + // Get the size of the Stream Metadata Packet + size_t streamMetadataPacketsize = GetPacketSize(mockStreamCounterBuffer, totalWrittenSize); + totalWrittenSize += streamMetadataPacketsize; + + sendCounterPacket.SetReadyToRead(); + + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + + sendCounterPacket.SendCounterDirectoryPacket(counterDirectory); + + // Get the size of the Counter Directory Packet + size_t counterDirectoryPacketSize = GetPacketSize(mockStreamCounterBuffer, totalWrittenSize); + totalWrittenSize += counterDirectoryPacketSize; + + sendCounterPacket.SetReadyToRead(); + + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + + sendCounterPacket.SendPeriodicCounterCapturePacket(123u, + { + { 1u, 23u }, + { 33u, 1207623u } + }); + + // Get the size of the Periodic Counter Capture Packet + size_t periodicCounterCapturePacketSize = GetPacketSize(mockStreamCounterBuffer, totalWrittenSize); + totalWrittenSize += periodicCounterCapturePacketSize; + + sendCounterPacket.SetReadyToRead(); + + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + + sendCounterPacket.SendPeriodicCounterCapturePacket(44u, + { + { 211u, 923u } + }); + + // Get the size of the Periodic Counter Capture Packet + periodicCounterCapturePacketSize = GetPacketSize(mockStreamCounterBuffer, totalWrittenSize); + totalWrittenSize += periodicCounterCapturePacketSize; + + sendCounterPacket.SendPeriodicCounterCapturePacket(1234u, + { + { 555u, 23u }, + { 556u, 6u }, + { 557u, 893454u }, + { 558u, 1456623u }, + { 559u, 571090u } + }); + + // Get the size of the Periodic Counter Capture Packet + periodicCounterCapturePacketSize = GetPacketSize(mockStreamCounterBuffer, totalWrittenSize); + totalWrittenSize += periodicCounterCapturePacketSize; + + sendCounterPacket.SendPeriodicCounterCapturePacket(997u, + { + { 88u, 11u }, + { 96u, 22u }, + { 97u, 33u }, + { 999u, 444u } + }); + + // Get the size of the Periodic Counter Capture Packet + periodicCounterCapturePacketSize = GetPacketSize(mockStreamCounterBuffer, totalWrittenSize); + totalWrittenSize += periodicCounterCapturePacketSize; + + sendCounterPacket.SetReadyToRead(); + + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + + sendCounterPacket.SendPeriodicCounterSelectionPacket(1000u, { 1345u, 254u, 4536u, 408u, 54u, 6323u, 428u, 1u, 6u }); + + // Get the size of the Periodic Counter Capture Packet + periodicCounterCapturePacketSize = GetPacketSize(mockStreamCounterBuffer, totalWrittenSize); + totalWrittenSize += periodicCounterCapturePacketSize; + + sendCounterPacket.SetReadyToRead(); + + // To test an exact value of the "read size" in the mock buffer, wait a second to allow the send thread to + // read all what's remaining in the buffer + std::this_thread::sleep_for(std::chrono::seconds(1)); + + sendCounterPacket.Stop(); + + BOOST_CHECK(mockStreamCounterBuffer.GetBufferSize() == totalWrittenSize); + BOOST_CHECK(mockStreamCounterBuffer.GetCommittedSize() == totalWrittenSize); + BOOST_CHECK(mockStreamCounterBuffer.GetReadSize() == totalWrittenSize); +} + +BOOST_AUTO_TEST_CASE(SendThreadTest2) +{ + size_t totalWrittenSize = 0; + + MockProfilingConnection mockProfilingConnection; + MockStreamCounterBuffer mockStreamCounterBuffer(100); + SendCounterPacket sendCounterPacket(mockProfilingConnection, mockStreamCounterBuffer); + sendCounterPacket.Start(); + + // Adding many spurious "ready to read" signals throughout the test to check that the send thread is + // capable of handling unnecessary read requests + + std::this_thread::sleep_for(std::chrono::seconds(1)); + + sendCounterPacket.SetReadyToRead(); + + CounterDirectory counterDirectory; + sendCounterPacket.SendStreamMetaDataPacket(); + + // Get the size of the Stream Metadata Packet + size_t streamMetadataPacketsize = GetPacketSize(mockStreamCounterBuffer, totalWrittenSize); + totalWrittenSize += streamMetadataPacketsize; + + sendCounterPacket.SetReadyToRead(); + + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + + sendCounterPacket.SendCounterDirectoryPacket(counterDirectory); + + // Get the size of the Counter Directory Packet + size_t counterDirectoryPacketSize = GetPacketSize(mockStreamCounterBuffer, totalWrittenSize); + totalWrittenSize += counterDirectoryPacketSize; + + sendCounterPacket.SetReadyToRead(); + sendCounterPacket.SetReadyToRead(); + + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + + sendCounterPacket.SendPeriodicCounterCapturePacket(123u, + { + { 1u, 23u }, + { 33u, 1207623u } + }); + + // Get the size of the Periodic Counter Capture Packet + size_t periodicCounterCapturePacketSize = GetPacketSize(mockStreamCounterBuffer, totalWrittenSize); + totalWrittenSize += periodicCounterCapturePacketSize; + + sendCounterPacket.SetReadyToRead(); + + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + + sendCounterPacket.SetReadyToRead(); + sendCounterPacket.SetReadyToRead(); + sendCounterPacket.SetReadyToRead(); + + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + + sendCounterPacket.SetReadyToRead(); + sendCounterPacket.SendPeriodicCounterCapturePacket(44u, + { + { 211u, 923u } + }); + + // Get the size of the Periodic Counter Capture Packet + periodicCounterCapturePacketSize = GetPacketSize(mockStreamCounterBuffer, totalWrittenSize); + totalWrittenSize += periodicCounterCapturePacketSize; + + sendCounterPacket.SendPeriodicCounterCapturePacket(1234u, + { + { 555u, 23u }, + { 556u, 6u }, + { 557u, 893454u }, + { 558u, 1456623u }, + { 559u, 571090u } + }); + + // Get the size of the Periodic Counter Capture Packet + periodicCounterCapturePacketSize = GetPacketSize(mockStreamCounterBuffer, totalWrittenSize); + totalWrittenSize += periodicCounterCapturePacketSize; + + sendCounterPacket.SetReadyToRead(); + sendCounterPacket.SendPeriodicCounterCapturePacket(997u, + { + { 88u, 11u }, + { 96u, 22u }, + { 97u, 33u }, + { 999u, 444u } + }); + + // Get the size of the Periodic Counter Capture Packet + periodicCounterCapturePacketSize = GetPacketSize(mockStreamCounterBuffer, totalWrittenSize); + totalWrittenSize += periodicCounterCapturePacketSize; + + sendCounterPacket.SetReadyToRead(); + sendCounterPacket.SetReadyToRead(); + + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + + sendCounterPacket.SendPeriodicCounterSelectionPacket(1000u, { 1345u, 254u, 4536u, 408u, 54u, 6323u, 428u, 1u, 6u }); + + // Get the size of the Periodic Counter Capture Packet + periodicCounterCapturePacketSize = GetPacketSize(mockStreamCounterBuffer, totalWrittenSize); + totalWrittenSize += periodicCounterCapturePacketSize; + + sendCounterPacket.SetReadyToRead(); + + // To test an exact value of the "read size" in the mock buffer, wait a second to allow the send thread to + // read all what's remaining in the buffer + std::this_thread::sleep_for(std::chrono::seconds(1)); + + sendCounterPacket.Stop(); + + BOOST_CHECK(mockStreamCounterBuffer.GetBufferSize() == totalWrittenSize); + BOOST_CHECK(mockStreamCounterBuffer.GetCommittedSize() == totalWrittenSize); + BOOST_CHECK(mockStreamCounterBuffer.GetReadSize() == totalWrittenSize); +} + +BOOST_AUTO_TEST_CASE(SendThreadTest3) +{ + size_t totalWrittenSize = 0; + + MockProfilingConnection mockProfilingConnection; + MockStreamCounterBuffer mockStreamCounterBuffer(100); + SendCounterPacket sendCounterPacket(mockProfilingConnection, mockStreamCounterBuffer); + sendCounterPacket.Start(); + + // Not using pauses or "grace periods" to stress test the send thread + + sendCounterPacket.SetReadyToRead(); + + CounterDirectory counterDirectory; + sendCounterPacket.SendStreamMetaDataPacket(); + + // Get the size of the Stream Metadata Packet + size_t streamMetadataPacketsize = GetPacketSize(mockStreamCounterBuffer, totalWrittenSize); + totalWrittenSize += streamMetadataPacketsize; + + sendCounterPacket.SetReadyToRead(); + sendCounterPacket.SendCounterDirectoryPacket(counterDirectory); + + // Get the size of the Counter Directory Packet + size_t counterDirectoryPacketSize = GetPacketSize(mockStreamCounterBuffer, totalWrittenSize); + totalWrittenSize += counterDirectoryPacketSize; + + sendCounterPacket.SetReadyToRead(); + sendCounterPacket.SetReadyToRead(); + sendCounterPacket.SendPeriodicCounterCapturePacket(123u, + { + { 1u, 23u }, + { 33u, 1207623u } + }); + + // Get the size of the Periodic Counter Capture Packet + size_t periodicCounterCapturePacketSize = GetPacketSize(mockStreamCounterBuffer, totalWrittenSize); + totalWrittenSize += periodicCounterCapturePacketSize; + + sendCounterPacket.SetReadyToRead(); + sendCounterPacket.SetReadyToRead(); + sendCounterPacket.SetReadyToRead(); + sendCounterPacket.SetReadyToRead(); + sendCounterPacket.SetReadyToRead(); + sendCounterPacket.SendPeriodicCounterCapturePacket(44u, + { + { 211u, 923u } + }); + + // Get the size of the Periodic Counter Capture Packet + periodicCounterCapturePacketSize = GetPacketSize(mockStreamCounterBuffer, totalWrittenSize); + totalWrittenSize += periodicCounterCapturePacketSize; + + sendCounterPacket.SendPeriodicCounterCapturePacket(1234u, + { + { 555u, 23u }, + { 556u, 6u }, + { 557u, 893454u }, + { 558u, 1456623u }, + { 559u, 571090u } + }); + + // Get the size of the Periodic Counter Capture Packet + periodicCounterCapturePacketSize = GetPacketSize(mockStreamCounterBuffer, totalWrittenSize); + totalWrittenSize += periodicCounterCapturePacketSize; + + sendCounterPacket.SetReadyToRead(); + sendCounterPacket.SetReadyToRead(); + sendCounterPacket.SendPeriodicCounterCapturePacket(997u, + { + { 88u, 11u }, + { 96u, 22u }, + { 97u, 33u }, + { 999u, 444u } + }); + + // Get the size of the Periodic Counter Capture Packet + periodicCounterCapturePacketSize = GetPacketSize(mockStreamCounterBuffer, totalWrittenSize); + totalWrittenSize += periodicCounterCapturePacketSize; + + sendCounterPacket.SetReadyToRead(); + sendCounterPacket.SetReadyToRead(); + sendCounterPacket.SendPeriodicCounterSelectionPacket(1000u, { 1345u, 254u, 4536u, 408u, 54u, 6323u, 428u, 1u, 6u }); + + // Get the size of the Periodic Counter Capture Packet + periodicCounterCapturePacketSize = GetPacketSize(mockStreamCounterBuffer, totalWrittenSize); + totalWrittenSize += periodicCounterCapturePacketSize; + + sendCounterPacket.SetReadyToRead(); + + // Abruptly terminating the send thread, the amount of data sent may be less that the amount written (the send + // thread is not guaranteed to flush the buffer) + sendCounterPacket.Stop(); + + BOOST_CHECK(mockStreamCounterBuffer.GetBufferSize() == totalWrittenSize); + BOOST_CHECK(mockStreamCounterBuffer.GetCommittedSize() == totalWrittenSize); + BOOST_CHECK(mockStreamCounterBuffer.GetReadSize() <= totalWrittenSize); +} + BOOST_AUTO_TEST_SUITE_END() diff --git a/src/profiling/test/SendCounterPacketTests.hpp b/src/profiling/test/SendCounterPacketTests.hpp index 5d5dfd14c7..3616816ae2 100644 --- a/src/profiling/test/SendCounterPacketTests.hpp +++ b/src/profiling/test/SendCounterPacketTests.hpp @@ -5,24 +5,50 @@ #pragma once -#include "../SendCounterPacket.hpp" -#include "../ProfilingUtils.hpp" +#include +#include #include +#include +#include -#include +#include -#include -#include +namespace armnn +{ -using namespace armnn::profiling; +namespace profiling +{ + +class MockProfilingConnection : public IProfilingConnection +{ +public: + MockProfilingConnection() + : m_IsOpen(true) + {} + + bool IsOpen() override { return m_IsOpen; } + + void Close() override { m_IsOpen = false; } + + bool WritePacket(const unsigned char* buffer, uint32_t length) override + { + return buffer != nullptr && length > 0; + } + + Packet ReadPacket(uint32_t timeout) override { return Packet(); } + +private: + bool m_IsOpen; +}; class MockBuffer : public IBufferWrapper { public: MockBuffer(unsigned int size) - : m_BufferSize(size), - m_Buffer(std::make_unique(size)) {} + : m_BufferSize(size) + , m_Buffer(std::make_unique(size)) + {} unsigned char* Reserve(unsigned int requestedSize, unsigned int& reservedSize) override { @@ -46,13 +72,115 @@ public: return m_Buffer.get(); } - void Release( unsigned int size) override {} + void Release(unsigned int size) override {} private: unsigned int m_BufferSize; std::unique_ptr m_Buffer; }; +class MockStreamCounterBuffer : public IBufferWrapper +{ +public: + MockStreamCounterBuffer(unsigned int size) + : m_Buffer(size, 0) + , m_CommittedSize(0) + , m_ReadSize(0) + {} + + unsigned char* Reserve(unsigned int requestedSize, unsigned int& reservedSize) override + { + std::unique_lock(m_Mutex); + + // Get the buffer size and the available size in the buffer past the committed size + size_t bufferSize = m_Buffer.size(); + size_t availableSize = bufferSize - m_CommittedSize; + + // Check whether the buffer needs to be resized + if (requestedSize > availableSize) + { + // Resize the buffer + size_t newSize = m_CommittedSize + requestedSize; + m_Buffer.resize(newSize, 0); + } + + // Set the reserved size + reservedSize = requestedSize; + + // Get a pointer to the beginning of the part of buffer available for writing + return m_Buffer.data() + m_CommittedSize; + } + + void Commit(unsigned int size) override + { + std::unique_lock(m_Mutex); + + // Update the committed size + m_CommittedSize += size; + } + + const unsigned char* GetReadBuffer(unsigned int& size) override + { + std::unique_lock(m_Mutex); + + // Get the size available for reading + size = boost::numeric_cast(m_CommittedSize - m_ReadSize); + + // Get a pointer to the beginning of the part of buffer available for reading + const unsigned char* readBuffer = m_Buffer.data() + m_ReadSize; + + // Update the read size + m_ReadSize = m_CommittedSize; + + return readBuffer; + } + + void Release(unsigned int size) override + { + std::unique_lock(m_Mutex); + + if (size == 0) + { + // Nothing to release + return; + } + + // Get the buffer size + size_t bufferSize = m_Buffer.size(); + + // Remove the last "size" bytes from the buffer + if (size < bufferSize) + { + // Resize the buffer + size_t newSize = bufferSize - size; + m_Buffer.resize(newSize); + } + else + { + // Clear the whole buffer + m_Buffer.clear(); + } + } + + size_t GetBufferSize() const { return m_Buffer.size(); } + size_t GetCommittedSize() const { return m_CommittedSize; } + size_t GetReadSize() const { return m_ReadSize; } + const unsigned char* GetBuffer() const { return m_Buffer.data(); } + +private: + // This mock uses an ever-expanding vector to simulate a counter stream buffer + std::vector m_Buffer; + + // The size of the buffer that has been committed for reading + size_t m_CommittedSize; + + // The size of the buffer that has already been read + size_t m_ReadSize; + + // This mock buffer provides basic synchronization + std::mutex m_Mutex; +}; + class MockSendCounterPacket : public ISendCounterPacket { public: @@ -93,8 +221,7 @@ public: m_Buffer.Commit(reserved); } - void SetReadyToRead() override - {} + void SetReadyToRead() override {} private: IBufferWrapper& m_Buffer; @@ -307,8 +434,8 @@ private: class SendCounterPacketTest : public SendCounterPacket { public: - SendCounterPacketTest(IBufferWrapper& buffer) - : SendCounterPacket(buffer) + SendCounterPacketTest(IProfilingConnection& profilingconnection, IBufferWrapper& buffer) + : SendCounterPacket(profilingconnection, buffer) {} bool CreateDeviceRecordTest(const DevicePtr& device, @@ -340,3 +467,7 @@ public: return CreateCategoryRecord(category, counters, categoryRecord, errorMessage); } }; + +} // namespace profiling + +} // namespace armnn -- cgit v1.2.1