aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatteo Martincigh <matteo.martincigh@arm.com>2019-11-04 14:05:28 +0000
committerMatteo Martincigh <matteo.martincigh@arm.com>2019-11-06 15:50:10 +0000
commit5dc816e7d027170992e45d22ae11ae3000de9244 (patch)
treed96d8a759dd0bcd9b98df36698ded032caa13bd0
parent5edc8816118fcddb2681379db04c978041ce8b46 (diff)
downloadarmnn-5dc816e7d027170992e45d22ae11ae3000de9244.tar.gz
IVGCVSW-4065 Add a RecordEvent function
* Added RecordEvent utility function to the TimelineUtilityMethods class * Added new utility function to get a timestamp * Added unit tests Signed-off-by: Matteo Martincigh <matteo.martincigh@arm.com> Change-Id: Ia3f8fe7397915fa6c903ce0c0abab3047cea628c
-rw-r--r--src/profiling/PeriodicCounterCapture.cpp11
-rw-r--r--src/profiling/PeriodicCounterCapture.hpp3
-rw-r--r--src/profiling/ProfilingUtils.cpp16
-rw-r--r--src/profiling/ProfilingUtils.hpp6
-rw-r--r--src/profiling/TimelineUtilityMethods.cpp35
-rw-r--r--src/profiling/TimelineUtilityMethods.hpp2
-rw-r--r--src/profiling/test/TimelineUtilityMethodsTests.cpp133
7 files changed, 187 insertions, 19 deletions
diff --git a/src/profiling/PeriodicCounterCapture.cpp b/src/profiling/PeriodicCounterCapture.cpp
index f888bc045e..12e58f2800 100644
--- a/src/profiling/PeriodicCounterCapture.cpp
+++ b/src/profiling/PeriodicCounterCapture.cpp
@@ -92,18 +92,11 @@ void PeriodicCounterCapture::Capture(const IReadCounterValues& readCounterValues
values.emplace_back(std::make_pair(requestedId, counterValue));
}
- #if USE_CLOCK_MONOTONIC_RAW
- using clock = MonotonicClockRaw;
- #else
- using clock = std::chrono::steady_clock;
- #endif
-
// Take a timestamp
- auto timestamp = clock::now();
+ uint64_t timestamp = GetTimestamp();
// Write a Periodic Counter Capture packet to the Counter Stream Buffer
- m_SendCounterPacket.SendPeriodicCounterCapturePacket(
- static_cast<uint64_t>(timestamp.time_since_epoch().count()), values);
+ m_SendCounterPacket.SendPeriodicCounterCapturePacket(timestamp, values);
// Notify the Send Thread that new data is available in the Counter Stream Buffer
m_SendCounterPacket.SetReadyToRead();
diff --git a/src/profiling/PeriodicCounterCapture.hpp b/src/profiling/PeriodicCounterCapture.hpp
index 4a28711d6b..9229a49d85 100644
--- a/src/profiling/PeriodicCounterCapture.hpp
+++ b/src/profiling/PeriodicCounterCapture.hpp
@@ -11,10 +11,7 @@
#include "SendCounterPacket.hpp"
#include "ICounterValues.hpp"
-#include <WallClockTimer.hpp>
-
#include <atomic>
-#include <chrono>
#include <mutex>
#include <thread>
diff --git a/src/profiling/ProfilingUtils.cpp b/src/profiling/ProfilingUtils.cpp
index 4202b68662..b649747df1 100644
--- a/src/profiling/ProfilingUtils.cpp
+++ b/src/profiling/ProfilingUtils.cpp
@@ -8,6 +8,8 @@
#include <armnn/Version.hpp>
#include <armnn/Conversion.hpp>
+#include <WallClockTimer.hpp>
+
#include <boost/assert.hpp>
#include <fstream>
@@ -889,7 +891,6 @@ TimelinePacketStatus WriteTimelineEventBinaryPacket(uint64_t timestamp,
return TimelinePacketStatus::Ok;
}
-
std::string CentreAlignFormatting(const std::string& stringToPass, const int spacingWidth)
{
std::stringstream outputStream, centrePadding;
@@ -1090,6 +1091,19 @@ void PrintCounterDirectory(ICounterDirectory& counterDirectory)
std::cout << "\n";
}
+uint64_t GetTimestamp()
+{
+#if USE_CLOCK_MONOTONIC_RAW
+ using clock = MonotonicClockRaw;
+#else
+ using clock = std::chrono::steady_clock;
+#endif
+
+ // Take a timestamp
+ auto timestamp = clock::now();
+
+ return static_cast<uint64_t>(timestamp.time_since_epoch().count());
+}
} // namespace profiling
diff --git a/src/profiling/ProfilingUtils.hpp b/src/profiling/ProfilingUtils.hpp
index fae1a83024..74fc437333 100644
--- a/src/profiling/ProfilingUtils.hpp
+++ b/src/profiling/ProfilingUtils.hpp
@@ -202,9 +202,11 @@ class BufferExhaustion : public armnn::Exception
using Exception::Exception;
};
-} // namespace profiling
+uint64_t GetTimestamp();
-} // namespace armnn
+} // namespace profiling
+
+} // namespace armnn
namespace std
{
diff --git a/src/profiling/TimelineUtilityMethods.cpp b/src/profiling/TimelineUtilityMethods.cpp
index 65668697f7..8c84aa73e9 100644
--- a/src/profiling/TimelineUtilityMethods.cpp
+++ b/src/profiling/TimelineUtilityMethods.cpp
@@ -157,6 +157,41 @@ ProfilingDynamicGuid TimelineUtilityMethods::CreateNamedTypedChildEntity(Profili
return childEntityGuid;
}
+ProfilingDynamicGuid TimelineUtilityMethods::RecordEvent(ProfilingGuid entityGuid, ProfilingStaticGuid eventClassGuid)
+{
+ // Take a timestamp
+ uint64_t timestamp = GetTimestamp();
+
+ // Get the thread id
+ std::thread::id threadId = std::this_thread::get_id();
+
+ // Generate a GUID for the event
+ ProfilingDynamicGuid eventGuid = ProfilingService::Instance().NextGuid();
+
+ // Send the new timeline event to the external profiling service, this call throws in case of error
+ m_SendTimelinePacket.SendTimelineEventBinaryPacket(timestamp, threadId, eventGuid);
+
+ // Generate a GUID for the execution link
+ ProfilingDynamicGuid executionLinkId = ProfilingService::Instance().NextGuid();
+
+ // Send the new execution link to the external profiling service, this call throws in case of error
+ m_SendTimelinePacket.SendTimelineRelationshipBinaryPacket(ProfilingRelationshipType::ExecutionLink,
+ executionLinkId,
+ entityGuid,
+ eventGuid);
+
+ // Generate a GUID for the data relationship link
+ ProfilingDynamicGuid eventClassLinkId = ProfilingService::Instance().NextGuid();
+
+ // Send the new data relationship link to the external profiling service, this call throws in case of error
+ m_SendTimelinePacket.SendTimelineRelationshipBinaryPacket(ProfilingRelationshipType::DataLink,
+ eventClassLinkId,
+ entityGuid,
+ eventClassGuid);
+
+ return eventGuid;
+}
+
} // namespace profiling
} // namespace armnn
diff --git a/src/profiling/TimelineUtilityMethods.hpp b/src/profiling/TimelineUtilityMethods.hpp
index 5f713bf6d4..5bb4342197 100644
--- a/src/profiling/TimelineUtilityMethods.hpp
+++ b/src/profiling/TimelineUtilityMethods.hpp
@@ -38,6 +38,8 @@ public:
const std::string& entityName,
const std::string& entityType);
+ ProfilingDynamicGuid RecordEvent(ProfilingGuid entityGuid, ProfilingStaticGuid eventClassGuid);
+
private:
ISendTimelinePacket& m_SendTimelinePacket;
};
diff --git a/src/profiling/test/TimelineUtilityMethodsTests.cpp b/src/profiling/test/TimelineUtilityMethodsTests.cpp
index c2be6e5c46..3556a12a7b 100644
--- a/src/profiling/test/TimelineUtilityMethodsTests.cpp
+++ b/src/profiling/test/TimelineUtilityMethodsTests.cpp
@@ -262,9 +262,8 @@ void VerifyTimelineEntityBinaryPacket(Optional<ProfilingGuid> guid,
// Check the decl_id
offset += uint32_t_size;
- uint32_t entitytDecId = ReadUint32(readableData, offset);
-
- BOOST_CHECK(entitytDecId == uint32_t(1));
+ uint32_t entityDeclId = ReadUint32(readableData, offset);
+ BOOST_CHECK(entityDeclId == 1);
// Check the profiling GUID
offset += uint32_t_size;
@@ -282,6 +281,83 @@ void VerifyTimelineEntityBinaryPacket(Optional<ProfilingGuid> guid,
offset += uint64_t_size;
}
+void VerifyTimelineEventBinaryPacket(Optional<uint64_t> timestamp,
+ Optional<std::thread::id> threadId,
+ Optional<ProfilingGuid> eventGuid,
+ const unsigned char* readableData,
+ unsigned int& offset)
+{
+ BOOST_ASSERT(readableData);
+
+ // Utils
+ unsigned int uint32_t_size = sizeof(uint32_t);
+ unsigned int uint64_t_size = sizeof(uint64_t);
+ unsigned int threadId_size = sizeof(std::thread::id);
+
+ // Reading TimelineEventBinaryPacket
+ uint32_t entityBinaryPacketHeaderWord0 = ReadUint32(readableData, offset);
+ uint32_t entityBinaryPacketFamily = (entityBinaryPacketHeaderWord0 >> 26) & 0x0000003F;
+ uint32_t entityBinaryPacketClass = (entityBinaryPacketHeaderWord0 >> 19) & 0x0000007F;
+ uint32_t entityBinaryPacketType = (entityBinaryPacketHeaderWord0 >> 16) & 0x00000007;
+ uint32_t entityBinaryPacketStreamId = (entityBinaryPacketHeaderWord0 >> 0) & 0x00000007;
+
+ BOOST_CHECK(entityBinaryPacketFamily == 1);
+ BOOST_CHECK(entityBinaryPacketClass == 0);
+ BOOST_CHECK(entityBinaryPacketType == 1);
+ BOOST_CHECK(entityBinaryPacketStreamId == 0);
+
+ offset += uint32_t_size;
+ uint32_t entityBinaryPacketHeaderWord1 = ReadUint32(readableData, offset);
+ uint32_t entityBinaryPacketSequenceNumbered = (entityBinaryPacketHeaderWord1 >> 24) & 0x00000001;
+ uint32_t entityBinaryPacketDataLength = (entityBinaryPacketHeaderWord1 >> 0) & 0x00FFFFFF;
+ BOOST_CHECK(entityBinaryPacketSequenceNumbered == 0);
+ BOOST_CHECK(entityBinaryPacketDataLength == 20 + threadId_size);
+
+ // Check the decl_id
+ offset += uint32_t_size;
+ uint32_t entityDeclId = ReadUint32(readableData, offset);
+ BOOST_CHECK(entityDeclId == 4);
+
+ // Check the timestamp
+ offset += uint32_t_size;
+ uint64_t readTimestamp = ReadUint64(readableData, offset);
+ if (timestamp.has_value())
+ {
+ BOOST_CHECK(readTimestamp == timestamp.value());
+ }
+ else
+ {
+ BOOST_CHECK(readTimestamp != 0);
+ }
+
+ // Check the thread id
+ offset += uint64_t_size;
+ std::vector<uint8_t> readThreadId(threadId_size, 0);
+ ReadBytes(readableData, offset, threadId_size, readThreadId.data());
+ if (threadId.has_value())
+ {
+ BOOST_CHECK(readThreadId == threadId.value());
+ }
+ else
+ {
+ BOOST_CHECK(readThreadId == std::this_thread::get_id());
+ }
+
+ // Check the event GUID
+ offset += threadId_size;
+ uint64_t readEventGuid = ReadUint64(readableData, offset);
+ if (eventGuid.has_value())
+ {
+ BOOST_CHECK(readEventGuid == eventGuid.value());
+ }
+ else
+ {
+ BOOST_CHECK(readEventGuid != ProfilingGuid(0));
+ }
+
+ offset += uint64_t_size;
+}
+
} // Anonymous namespace
BOOST_AUTO_TEST_SUITE(TimelineUtilityMethodsTests)
@@ -518,7 +594,7 @@ BOOST_AUTO_TEST_CASE(CreateNameTypeEntityInvalidTest)
}
-BOOST_AUTO_TEST_CASE(CreateNameTypeEntitylTest)
+BOOST_AUTO_TEST_CASE(CreateNameTypeEntityTest)
{
MockBufferManager mockBufferManager(1024);
SendTimelinePacket sendTimelinePacket(mockBufferManager);
@@ -591,4 +667,53 @@ BOOST_AUTO_TEST_CASE(CreateNameTypeEntitylTest)
mockBufferManager.MarkRead(readableBuffer);
}
+BOOST_AUTO_TEST_CASE(RecordEventTest)
+{
+ MockBufferManager mockBufferManager(1024);
+ SendTimelinePacket sendTimelinePacket(mockBufferManager);
+ TimelineUtilityMethods timelineUtilityMethods(sendTimelinePacket);
+
+ ProfilingGuid entityGuid(123);
+ ProfilingStaticGuid eventClassGuid(456);
+ ProfilingDynamicGuid eventGuid(0);
+ BOOST_CHECK_NO_THROW(eventGuid = timelineUtilityMethods.RecordEvent(entityGuid, eventClassGuid));
+ BOOST_CHECK(eventGuid != ProfilingGuid(0));
+
+ // Commit all packets at once
+ sendTimelinePacket.Commit();
+
+ // Get the readable buffer
+ auto readableBuffer = mockBufferManager.GetReadableBuffer();
+ BOOST_CHECK(readableBuffer != nullptr);
+ unsigned int size = readableBuffer->GetSize();
+ BOOST_CHECK(size == 116);
+ const unsigned char* readableData = readableBuffer->GetReadableData();
+ BOOST_CHECK(readableData != nullptr);
+
+ // Utils
+ unsigned int offset = 0;
+
+ // First packet sent: TimelineEntityBinaryPacket
+ VerifyTimelineEventBinaryPacket(EmptyOptional(), EmptyOptional(), EmptyOptional(), readableData, offset);
+
+ // Second packet sent: TimelineRelationshipBinaryPacket
+ VerifyTimelineRelationshipBinaryPacket(ProfilingRelationshipType::ExecutionLink,
+ EmptyOptional(),
+ entityGuid,
+ EmptyOptional(),
+ readableData,
+ offset);
+
+ // Third packet sent: TimelineRelationshipBinaryPacket
+ VerifyTimelineRelationshipBinaryPacket(ProfilingRelationshipType::DataLink,
+ EmptyOptional(),
+ entityGuid,
+ eventClassGuid,
+ readableData,
+ offset);
+
+ // Mark the buffer as read
+ mockBufferManager.MarkRead(readableBuffer);
+}
+
BOOST_AUTO_TEST_SUITE_END()