IVGCVSW-4065 Add a RecordEvent function
[platform/upstream/armnn.git] / src / profiling / PeriodicCounterCapture.cpp
1 //
2 // Copyright © 2019 Arm Ltd. All rights reserved.
3 // SPDX-License-Identifier: MIT
4 //
5
6 #include "PeriodicCounterCapture.hpp"
7
8 #include <boost/log/trivial.hpp>
9 #include <iostream>
10
11 namespace armnn
12 {
13
14 namespace profiling
15 {
16
17 void PeriodicCounterCapture::Start()
18 {
19     // Check if the capture thread is already running
20     if (m_IsRunning)
21     {
22         // The capture thread is already running
23         return;
24     }
25
26     // Mark the capture thread as running
27     m_IsRunning = true;
28
29     // Keep the capture procedure going until the capture thread is signalled to stop
30     m_KeepRunning.store(true);
31
32     // Start the new capture thread.
33     m_PeriodCaptureThread = std::thread(&PeriodicCounterCapture::Capture, this, std::ref(m_ReadCounterValues));
34 }
35
36 void PeriodicCounterCapture::Stop()
37 {
38     // Signal the capture thread to stop
39     m_KeepRunning.store(false);
40
41     // Check that the capture thread is running
42     if (m_PeriodCaptureThread.joinable())
43     {
44         // Wait for the capture thread to complete operations
45         m_PeriodCaptureThread.join();
46     }
47
48     // Mark the capture thread as not running
49     m_IsRunning = false;
50 }
51
52 CaptureData PeriodicCounterCapture::ReadCaptureData()
53 {
54     return m_CaptureDataHolder.GetCaptureData();
55 }
56
57 void PeriodicCounterCapture::Capture(const IReadCounterValues& readCounterValues)
58 {
59     do
60     {
61         // Check if the current capture data indicates that there's data capture
62         auto currentCaptureData = ReadCaptureData();
63         const std::vector<uint16_t>& counterIds = currentCaptureData.GetCounterIds();
64
65         if (currentCaptureData.GetCapturePeriod() == 0 || counterIds.empty())
66         {
67             // No data capture, wait the indicated capture period (milliseconds)
68             std::this_thread::sleep_for(std::chrono::milliseconds(5));
69             continue;
70         }
71
72         std::vector<std::pair<uint16_t, uint32_t>> values;
73         auto numCounters = counterIds.size();
74         values.reserve(numCounters);
75
76         // Create a vector of pairs of CounterIndexes and Values
77         for (uint16_t index = 0; index < numCounters; ++index)
78         {
79             auto requestedId = counterIds[index];
80             uint32_t counterValue = 0;
81             try
82             {
83                 counterValue = readCounterValues.GetCounterValue(requestedId);
84             }
85             catch (const Exception& e)
86             {
87                 // Report the error and continue
88                 BOOST_LOG_TRIVIAL(warning) << "An error has occurred when getting a counter value: "
89                                            << e.what() << std::endl;
90                 continue;
91             }
92             values.emplace_back(std::make_pair(requestedId, counterValue));
93         }
94
95         // Take a timestamp
96         uint64_t timestamp = GetTimestamp();
97
98         // Write a Periodic Counter Capture packet to the Counter Stream Buffer
99         m_SendCounterPacket.SendPeriodicCounterCapturePacket(timestamp, values);
100
101         // Notify the Send Thread that new data is available in the Counter Stream Buffer
102         m_SendCounterPacket.SetReadyToRead();
103
104         // Wait the indicated capture period (microseconds)
105         std::this_thread::sleep_for(std::chrono::microseconds(currentCaptureData.GetCapturePeriod()));
106
107     }
108     while (m_KeepRunning.load());
109 }
110
111 } // namespace profiling
112
113 } // namespace armnn