From 5238aff21baf0b35c36ab0cc72c7a46888e3bd08 Mon Sep 17 00:00:00 2001 From: Keith Davis Date: Wed, 11 Mar 2020 12:17:05 +0000 Subject: [PATCH] IVGCVSW-4542 Refactor TimelineDecoder parsing of TimelinePackets * Added test to add multiple SwTraceMessages to the buffer * Updated TimelineCaptureCommandHandler to iterate until there are no more read functions in the packet * Further commenting Change-Id: I41d5acf4f7288ce5a51ffd10a5eea335ac3026ec Signed-off-by: Keith Davis --- src/profiling/ProfilingUtils.hpp | 5 +- src/profiling/SendTimelinePacket.hpp | 3 +- .../TimelineCaptureCommandHandler.cpp | 43 +++++---- .../TimelineCaptureCommandHandler.hpp | 27 +++--- src/timelineDecoder/tests/TimelineTests.cpp | 105 +++++++++++++++++++++ 5 files changed, 154 insertions(+), 29 deletions(-) diff --git a/src/profiling/ProfilingUtils.hpp b/src/profiling/ProfilingUtils.hpp index 2604361..37ab88c 100644 --- a/src/profiling/ProfilingUtils.hpp +++ b/src/profiling/ProfilingUtils.hpp @@ -108,7 +108,10 @@ bool StringToSwTraceString(const std::string& s, std::vector& outputBu // Prepare the output buffer size_t s_size = s.size() + 1; // The size of the string (in chars) plus the null-terminator size_t uint32_t_size = sizeof(uint32_t); - size_t outBufferSize = 1 + s_size / uint32_t_size + (s_size % uint32_t_size != 0 ? 1 : 0); + // Output buffer size = StringLength (32 bit) + amount of complete 32bit words that fit into the string + // + an additional 32bit word if there are remaining chars to complete the string + // (The rest of the 32bit word is then filled with the NULL terminator) + size_t outBufferSize = 1 + (s_size / uint32_t_size) + (s_size % uint32_t_size != 0 ? 1 : 0); outputBuffer.resize(outBufferSize, '\0'); // Write the SWTrace string to the output buffer diff --git a/src/profiling/SendTimelinePacket.hpp b/src/profiling/SendTimelinePacket.hpp index b3b4aa1..3e52c97 100644 --- a/src/profiling/SendTimelinePacket.hpp +++ b/src/profiling/SendTimelinePacket.hpp @@ -98,7 +98,8 @@ void SendTimelinePacket::ForwardWriteBinaryFunction(Func& func, Params&& ... par throw RuntimeException("Error processing while sending TimelineBinaryPacket", CHECK_LOCATION()); - default:m_Offset += numberOfBytesWritten; + default: + m_Offset += numberOfBytesWritten; m_RemainingBufferSize -= numberOfBytesWritten; return; } diff --git a/src/timelineDecoder/TimelineCaptureCommandHandler.cpp b/src/timelineDecoder/TimelineCaptureCommandHandler.cpp index 01f55bd..fb6935e 100644 --- a/src/timelineDecoder/TimelineCaptureCommandHandler.cpp +++ b/src/timelineDecoder/TimelineCaptureCommandHandler.cpp @@ -26,8 +26,9 @@ const TimelineCaptureCommandHandler::ReadFunction TimelineCaptureCommandHandler: void TimelineCaptureCommandHandler::ParseData(const armnn::profiling::Packet& packet) { uint32_t offset = 0; + m_PacketLength = packet.GetLength(); - if (packet.GetLength() < 8) + if ( m_PacketLength < 8 ) { return; } @@ -36,13 +37,16 @@ void TimelineCaptureCommandHandler::ParseData(const armnn::profiling::Packet& pa uint32_t declId = 0; - declId = profiling::ReadUint32(data, offset); - offset += uint32_t_size; + while ( offset < m_PacketLength ) + { + declId = profiling::ReadUint32(data, offset); + offset += uint32_t_size; - (this->*m_ReadFunctions[declId])(data, offset); + (this->*m_ReadFunctions[declId])(data, offset); + } } -void TimelineCaptureCommandHandler::ReadLabel(const unsigned char* data, uint32_t offset) +void TimelineCaptureCommandHandler::ReadLabel(const unsigned char* data, uint32_t& offset) { ITimelineDecoder::Label label; label.m_Guid = profiling::ReadUint64(data, offset); @@ -51,30 +55,36 @@ void TimelineCaptureCommandHandler::ReadLabel(const unsigned char* data, uint32_ uint32_t nameLength = profiling::ReadUint32(data, offset); offset += uint32_t_size; - for (uint32_t i = 0; i < nameLength-1; ++i) + uint32_t i = 0; + // nameLength - 1 to account for null operator \0 + for ( i = 0; i < nameLength - 1; ++i ) { label.m_Name += static_cast(profiling::ReadUint8(data, offset + i)); } + // Shift offset past nameLength + uint32_t uint32WordAmount = (nameLength / uint32_t_size) + (nameLength % uint32_t_size != 0 ? 1 : 0); + offset += uint32WordAmount * uint32_t_size; + m_TimelineDecoder.CreateLabel(label); } -void TimelineCaptureCommandHandler::ReadEntity(const unsigned char* data, uint32_t offset) +void TimelineCaptureCommandHandler::ReadEntity(const unsigned char* data, uint32_t& offset) { ITimelineDecoder::Entity entity; entity.m_Guid = profiling::ReadUint64(data, offset); - + offset += uint64_t_size; m_TimelineDecoder.CreateEntity(entity); } -void TimelineCaptureCommandHandler::ReadEventClass(const unsigned char* data, uint32_t offset) +void TimelineCaptureCommandHandler::ReadEventClass(const unsigned char* data, uint32_t& offset) { ITimelineDecoder::EventClass eventClass; eventClass.m_Guid = profiling::ReadUint64(data, offset); - + offset += uint64_t_size; m_TimelineDecoder.CreateEventClass(eventClass); } -void TimelineCaptureCommandHandler::ReadRelationship(const unsigned char* data, uint32_t offset) +void TimelineCaptureCommandHandler::ReadRelationship(const unsigned char* data, uint32_t& offset) { ITimelineDecoder::Relationship relationship; relationship.m_RelationshipType = @@ -84,25 +94,25 @@ void TimelineCaptureCommandHandler::ReadRelationship(const unsigned char* data, relationship.m_Guid = profiling::ReadUint64(data, offset); offset += uint64_t_size; - relationship.m_HeadGuid = profiling::ReadUint64(data, offset); + relationship.m_HeadGuid = profiling::ReadUint64(data, offset); offset += uint64_t_size; relationship.m_TailGuid = profiling::ReadUint64(data, offset); - + offset += uint64_t_size; m_TimelineDecoder.CreateRelationship(relationship); } -void TimelineCaptureCommandHandler::ReadEvent(const unsigned char* data, uint32_t offset) +void TimelineCaptureCommandHandler::ReadEvent(const unsigned char* data, uint32_t& offset) { ITimelineDecoder::Event event; event.m_TimeStamp = profiling::ReadUint64(data, offset); offset += uint64_t_size; - if (m_ThreadIdSize == 4) + if ( m_ThreadIdSize == 4 ) { event.m_ThreadId = profiling::ReadUint32(data, offset); } - else if (m_ThreadIdSize == 8) + else if ( m_ThreadIdSize == 8 ) { event.m_ThreadId = profiling::ReadUint64(data, offset); } @@ -110,6 +120,7 @@ void TimelineCaptureCommandHandler::ReadEvent(const unsigned char* data, uint32_ offset += m_ThreadIdSize; event.m_Guid = profiling::ReadUint64(data, offset); + offset += uint64_t_size; m_TimelineDecoder.CreateEvent(event); } diff --git a/src/timelineDecoder/TimelineCaptureCommandHandler.hpp b/src/timelineDecoder/TimelineCaptureCommandHandler.hpp index d95adc0..b69e615 100644 --- a/src/timelineDecoder/TimelineCaptureCommandHandler.hpp +++ b/src/timelineDecoder/TimelineCaptureCommandHandler.hpp @@ -17,13 +17,14 @@ namespace armnn namespace timelinedecoder { -class TimelineCaptureCommandHandler : public profiling::CommandHandlerFunctor +class TimelineCaptureCommandHandler : + public profiling::CommandHandlerFunctor { // Utils uint32_t uint32_t_size = sizeof(uint32_t); uint32_t uint64_t_size = sizeof(uint64_t); - using ReadFunction = void (TimelineCaptureCommandHandler::*)(const unsigned char*, uint32_t); + using ReadFunction = void (TimelineCaptureCommandHandler::*)(const unsigned char*, uint32_t&); public: TimelineCaptureCommandHandler(uint32_t familyId, @@ -31,25 +32,29 @@ public: uint32_t version, ITimelineDecoder& timelineDecoder, uint32_t threadId_size) - : CommandHandlerFunctor(familyId, packetId, version) - , m_TimelineDecoder(timelineDecoder) - , m_ThreadIdSize(threadId_size) + : CommandHandlerFunctor(familyId, packetId, version), + m_TimelineDecoder(timelineDecoder), + m_ThreadIdSize(threadId_size), + m_PacketLength(0) {} void operator()(const armnn::profiling::Packet& packet) override; - void ReadLabel(const unsigned char* data, uint32_t offset); - void ReadEntity(const unsigned char* data, uint32_t offset); - void ReadEventClass(const unsigned char* data, uint32_t offset); - void ReadRelationship(const unsigned char* data, uint32_t offset); - void ReadEvent(const unsigned char* data, uint32_t offset); + void ReadLabel(const unsigned char* data, uint32_t& offset); + void ReadEntity(const unsigned char* data, uint32_t& offset); + void ReadEventClass(const unsigned char* data, uint32_t& offset); + void ReadRelationship(const unsigned char* data, uint32_t& offset); + void ReadEvent(const unsigned char* data, uint32_t& offset); private: void ParseData(const armnn::profiling::Packet& packet); ITimelineDecoder& m_TimelineDecoder; - const uint32_t m_ThreadIdSize; + + const uint32_t m_ThreadIdSize; + unsigned int m_PacketLength; static const ReadFunction m_ReadFunctions[]; + }; } //namespace gatordmock diff --git a/src/timelineDecoder/tests/TimelineTests.cpp b/src/timelineDecoder/tests/TimelineTests.cpp index 02d93c3..62b4330 100644 --- a/src/timelineDecoder/tests/TimelineTests.cpp +++ b/src/timelineDecoder/tests/TimelineTests.cpp @@ -248,4 +248,109 @@ BOOST_AUTO_TEST_CASE(TimelineCaptureTest) } } +BOOST_AUTO_TEST_CASE(TimelineCaptureTestMultipleStringsInBuffer) +{ + unsigned int threadIdSize = sizeof(std::thread::id); + profiling::BufferManager bufferManager(50); + profiling::TimelinePacketWriterFactory timelinePacketWriterFactory(bufferManager); + + std::unique_ptr sendTimelinePacket = + timelinePacketWriterFactory.GetSendTimelinePacket(); + + profiling::PacketVersionResolver packetVersionResolver; + + TimelineDecoder timelineDecoder; + const TimelineDecoder::Model& model = timelineDecoder.GetModel(); + + TimelineCaptureCommandHandler timelineCaptureCommandHandler( + 1, 1, packetVersionResolver.ResolvePacketVersion(1, 1).GetEncodedValue(), timelineDecoder, threadIdSize); + + using Status = ITimelineDecoder::TimelineStatus; + BOOST_CHECK(timelineDecoder.SetEntityCallback(PushEntity) == Status::TimelineStatus_Success); + BOOST_CHECK(timelineDecoder.SetEventClassCallback(PushEventClass) == Status::TimelineStatus_Success); + BOOST_CHECK(timelineDecoder.SetEventCallback(PushEvent) == Status::TimelineStatus_Success); + BOOST_CHECK(timelineDecoder.SetLabelCallback(PushLabel) == Status::TimelineStatus_Success); + BOOST_CHECK(timelineDecoder.SetRelationshipCallback(PushRelationship) == Status::TimelineStatus_Success); + + const uint64_t entityGuid = 111111u; + const uint64_t eventClassGuid = 22222u; + const uint64_t timestamp = 33333u; + const uint64_t eventGuid = 44444u; + + const std::thread::id threadId = std::this_thread::get_id(); + + // need to do a bit of work here to extract the value from threadId + unsigned char* uCharThreadId = new unsigned char[threadIdSize]();; + uint64_t uint64ThreadId; + + profiling::WriteBytes(uCharThreadId, 0, &threadId, threadIdSize); + + if ( threadIdSize == 4 ) + { + uint64ThreadId = profiling::ReadUint32(uCharThreadId, 0); + } else if ( threadIdSize == 8 ) + { + uint64ThreadId = profiling::ReadUint64(uCharThreadId, 0); + } + delete[] uCharThreadId; + + const uint64_t labelGuid = 66666u; + std::string labelName = "test_label"; + std::string labelName2 = "test_label2"; + std::string labelName3 = "test_label32"; + + const uint64_t relationshipGuid = 77777u; + const uint64_t headGuid = 888888u; + const uint64_t tailGuid = 999999u; + + // Check with multiple messages in the same buffer + for ( int i = 0; i < 9; ++i ) + { + // Send entity + sendTimelinePacket->SendTimelineEntityBinaryPacket(entityGuid); + // Send event class + sendTimelinePacket->SendTimelineEventClassBinaryPacket(eventClassGuid); + // Send event + sendTimelinePacket->SendTimelineEventBinaryPacket(timestamp, threadId, eventGuid); + // Send label + sendTimelinePacket->SendTimelineLabelBinaryPacket(labelGuid, labelName); + sendTimelinePacket->SendTimelineLabelBinaryPacket(labelGuid, labelName2); + sendTimelinePacket->SendTimelineLabelBinaryPacket(labelGuid, labelName3); + // Send relationship + profiling::ProfilingRelationshipType relationshipType = profiling::ProfilingRelationshipType::DataLink; + sendTimelinePacket->SendTimelineRelationshipBinaryPacket(relationshipType, + relationshipGuid, + headGuid, + tailGuid); + } + + sendTimelinePacket->Commit(); + SendTimelinePacketToCommandHandler(bufferManager.GetReadableBuffer()->GetReadableData(), + timelineCaptureCommandHandler); + + for ( unsigned long i = 0; i < 9; ++i ) + { + BOOST_CHECK(model.m_Entities[i].m_Guid == entityGuid); + + BOOST_CHECK(model.m_EventClasses[i].m_Guid == eventClassGuid); + + BOOST_CHECK(model.m_Labels[i].m_Guid == labelGuid); + + BOOST_CHECK(model.m_Events[i].m_TimeStamp == timestamp); + BOOST_CHECK(model.m_Events[i].m_ThreadId == uint64ThreadId); + BOOST_CHECK(model.m_Events[i].m_Guid == eventGuid); + + BOOST_CHECK(model.m_Relationships[i].m_RelationshipType == ITimelineDecoder::RelationshipType::DataLink); + BOOST_CHECK(model.m_Relationships[i].m_Guid == relationshipGuid); + BOOST_CHECK(model.m_Relationships[i].m_HeadGuid == headGuid); + BOOST_CHECK(model.m_Relationships[i].m_TailGuid == tailGuid); + } + for ( unsigned long i = 0; i < 9; i += 3 ) + { + BOOST_CHECK(model.m_Labels[i].m_Name == labelName); + BOOST_CHECK(model.m_Labels[i+1].m_Name == labelName2); + BOOST_CHECK(model.m_Labels[i+2].m_Name == labelName3); + } +} + BOOST_AUTO_TEST_SUITE_END() -- 2.7.4