Argus Camera Sample Argus Camera Sample

- Main Page
- Related Pages
- Namespaces
- Classes
- Files

- File List
- File Members

All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
PerfTracker.cpp
Go to the documentation of this file.
1 /*
2 * Copyright (c) 2016-2017, NVIDIA CORPORATION. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of NVIDIA CORPORATION nor the names of its
13 * contributors may be used to endorse or promote products derived
14 * from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
20 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
21 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
23 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
24 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29 #include "PerfTracker.h"
30
31 #include <stdio.h>
32 #define __STDC_FORMAT_MACROS
33 #include <inttypes.h>
34
35 #include <limits>
36
37 #include "Dispatcher.h"
38 #include "EventThread.h"
39 #include "InitOnce.h"
40
41 namespace ArgusSamples
42 {
43
44 PerfTracker::PerfTracker()
45 : m_sessionId(0)
46 {
47 }
48
49 PerfTracker::~PerfTracker()
50 {
51 }
52
53 bool PerfTracker::initialize()
54 {
55 m_sessionId = 0;
56 m_displayCount = 0;
57 return true;
58 }
59
60 PerfTracker &PerfTracker::getInstance()
61 {
62 static InitOnce initOnce;
63 static PerfTracker instance;
64
65 if (initOnce.begin())
66 {
67 if (instance.initialize())
68 {
69 initOnce.complete();
70 }
71 else
72 {
73 initOnce.failed();
74 REPORT_ERROR("Initalization failed");
75 }
76 }
77
78 return instance;
79 }
80
81 bool PerfTracker::onEvent(GlobalEvent event)
82 {
83 switch (event)
84 {
85 case GLOBAL_EVENT_APP_START:
86 m_appStartTime = getCurrentTime();
87 break;
88 case GLOBAL_EVENT_APP_INITIALIZED:
89 m_appInitializedTime = getCurrentTime();
90 break;
91 case GLOBAL_EVENT_DISPLAY:
92 if (!Dispatcher::getInstance().m_kpi)
93 return true;
94
95 if (m_firstDisplayTime == TimeValue())
96 {
97 // start measurement
98 m_firstDisplayTime = getCurrentTime();
99 }
100 else
101 {
102 const TimeValue curTime = getCurrentTime();
103
104 m_displayCount++;
105
106 // print every second
107 if (curTime - m_firstDisplayTime > TimeValue::fromSec(1.f))
108 {
109 const float frameRate = static_cast<float>(m_displayCount) *
110 (curTime - m_firstDisplayTime).toCyclesPerSec();
111 printf("PerfTracker: display frame rate %.2f frames per second\n", frameRate);
112
113 // restart measurement
114 m_firstDisplayTime = getCurrentTime();
115 m_displayCount = 0;
116 }
117 }
118 break;
119 default:
120 ORIGINATE_ERROR("Unhandled global event");
121 break;
122 }
123
124 return true;
125 }
126
127 SessionPerfTracker::SessionPerfTracker()
128 : m_id(PerfTracker::getInstance().getNewSessionID())
129 , m_session(NULL)
130 , m_numberframesReceived(0)
131 , m_lastFrameCount(0)
132 , m_totalFrameDrop(0)
133 , m_minLatency(std::numeric_limits<uint64_t>::max())
134 , m_maxLatency(0)
135 , m_sumLatency(0)
136 , m_countLatency(0)
137 {
138 }
139
140 SessionPerfTracker::~SessionPerfTracker()
141 {
142 PROPAGATE_ERROR_CONTINUE(shutdown());
143 }
144
145 bool SessionPerfTracker::shutdown()
146 {
147 if (m_eventThread)
148 {
149 PROPAGATE_ERROR_CONTINUE(m_eventThread->shutdown());
150 m_eventThread.reset();
151 }
152
153 return true;
154 }
155
156 bool SessionPerfTracker::setSession(Argus::CaptureSession *session)
157 {
158 m_session = session;
159 return true;
160 }
161
162 bool SessionPerfTracker::onEvent(SessionEvent event, uint64_t value)
163 {
164 if (!Dispatcher::getInstance().m_kpi)
165 return true;
166
167 switch (event)
168 {
169 case SESSION_EVENT_TASK_START:
170 m_taskStartTime = getCurrentTime();
171 printf("PerfTracker: app initial %" PRIu64 " ms\n",
172 (PerfTracker::getInstance().appInitializedTime() -
173 PerfTracker::getInstance().appStartTime()).toMSec());
174 printf("PerfTracker %d: app intialized to task start %" PRIu64 " ms\n", m_id,
175 (m_taskStartTime - PerfTracker::getInstance().appInitializedTime()).toMSec());
176 break;
177 case SESSION_EVENT_ISSUE_CAPTURE:
178 // captures are about to start, create the event thread which collects information on the
179 // captures received
180 if (!m_eventThread)
181 {
182 m_eventThread.reset(new EventThread(m_session, this));
183 if (!m_eventThread)
184 ORIGINATE_ERROR("Failed to allocate EventThread");
185
186 PROPAGATE_ERROR(m_eventThread->initialize());
187 PROPAGATE_ERROR(m_eventThread->waitRunning());
188 }
189
190 m_issueCaptureTime = getCurrentTime();
191 printf("PerfTracker %d: task start to issue capture %" PRIu64 " ms\n", m_id,
192 (m_issueCaptureTime - m_taskStartTime).toMSec());
193 break;
194 case SESSION_EVENT_REQUEST_RECEIVED:
195 m_requestReceivedTime = getCurrentTime();
196 if (m_numberframesReceived == 0)
197 {
198 m_firstRequestReceivedTime = m_requestReceivedTime;
199 printf("PerfTracker %d: first request %" PRIu64 " ms\n", m_id,
200 (m_firstRequestReceivedTime - m_issueCaptureTime).toMSec());
201 printf("PerfTracker %d: total launch time %" PRIu64 " ms\n", m_id,
202 (m_firstRequestReceivedTime - PerfTracker::getInstance().appStartTime()).toMSec());
203 }
204
205 m_numberframesReceived++;
206 if ((m_numberframesReceived % 30) == 2)
207 {
208 const float frameRate =
209 static_cast<float>(m_numberframesReceived - 1) *
210 (m_requestReceivedTime - m_firstRequestReceivedTime).toCyclesPerSec();
211 printf("PerfTracker %d: frameRate %.2f frames per second at %" PRIu64 " Seconds\n",
212 m_id,
213 frameRate,
214 (m_requestReceivedTime - m_firstRequestReceivedTime).toSec());
215 }
216 break;
217 case SESSION_EVENT_REQUEST_LATENCY:
218 // can do some stats
219 m_minLatency = (m_minLatency < value) ? m_minLatency : value;
220 m_maxLatency = (m_maxLatency < value) ? value : m_maxLatency;
221 m_sumLatency += value;
222 m_countLatency += 1;
223 if ((m_numberframesReceived % 30) == 6)
224 {
225 const uint64_t latencyAverage = (m_sumLatency + m_countLatency/2) / m_countLatency;
226 printf("PerfTracker %d: latency %" PRIu64 " ms average, min %" PRIu64
227 " max %" PRIu64 "\n",
228 m_id, latencyAverage,
229 m_minLatency,
230 m_maxLatency);
231
232 m_countLatency = 0;
233 m_sumLatency = 0;
234 m_maxLatency = 0;
235 m_minLatency = std::numeric_limits<uint64_t>::max();
236 }
237 break;
238 case SESSION_EVENT_FRAME_COUNT:
239 {
240 const TimeValue currentTime = getCurrentTime();
241 const uint64_t currentFrameCount = value;
242 int64_t currentFrameDrop = 0;
243 // start frame drop count from 2nd frame
244 if (m_lastFrameCount > 0)
245 {
246 // currentFrameDrop can be negative when metadata comes out of order
247 currentFrameDrop = currentFrameCount - m_lastFrameCount - 1;
248 m_totalFrameDrop += currentFrameDrop;
249 }
250 if (currentFrameDrop != 0)
251 {
252 printf("PerfTracker %d: framedrop current request %" PRId64 ", total %" PRId64
253 ", Drop at %" PRIu64 " Seconds !\n",
254 m_id, currentFrameDrop,
255 m_totalFrameDrop,
256 (currentTime - m_firstRequestReceivedTime).toSec());
257 }
258 else
259 {
260 if ((m_numberframesReceived % 30) == 4)
261 {
262 printf("PerfTracker %d: framedrop current request %" PRId64 ", total %"
263 PRId64 "\n",
264 m_id, currentFrameDrop,
265 m_totalFrameDrop);
266 }
267 }
268
269 m_lastFrameCount = currentFrameCount;
270 break;
271 }
272 case SESSION_EVENT_CLOSE_REQUESTED:
273 m_closeRequestedTime = getCurrentTime();
274 // captures are about to be stopped, destroy the event thread.
275 if (m_eventThread)
276 {
277 PROPAGATE_ERROR(m_eventThread->shutdown());
278 m_eventThread.reset();
279 }
280 break;
281 case SESSION_EVENT_FLUSH_DONE:
282 m_flushDoneTime = getCurrentTime();
283 printf("PerfTracker %d: flush takes %" PRIu64 " ms\n", m_id,
284 (m_flushDoneTime - m_closeRequestedTime).toMSec());
285 break;
286 case SESSION_EVENT_CLOSE_DONE:
287 m_closeDoneTime = getCurrentTime();
288 printf("PerfTracker %d: device close takes %" PRIu64 " ms\n", m_id,
289 (m_closeDoneTime - m_flushDoneTime).toMSec());
290 printf("PerfTracker %d: total close takes %" PRIu64 " ms\n", m_id,
291 (m_closeDoneTime - m_closeRequestedTime).toMSec());
292 break;
293 default:
294 ORIGINATE_ERROR("Unhandled session event");
295 break;
296 }
297
298 return true;
299 }
300
301 }; // namespace ArgusSamples