00001 /* 00002 * Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved. 00003 * 00004 * Redistribution and use in source and binary forms, with or without 00005 * modification, are permitted provided that the following conditions 00006 * are met: 00007 * * Redistributions of source code must retain the above copyright 00008 * notice, this list of conditions and the following disclaimer. 00009 * * Redistributions in binary form must reproduce the above copyright 00010 * notice, this list of conditions and the following disclaimer in the 00011 * documentation and/or other materials provided with the distribution. 00012 * * Neither the name of NVIDIA CORPORATION nor the names of its 00013 * contributors may be used to endorse or promote products derived 00014 * from this software without specific prior written permission. 00015 * 00016 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY 00017 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00018 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 00019 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 00020 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 00021 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 00022 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 00023 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 00024 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 00025 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 00026 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00027 */ 00028 00029 #ifndef __NV_ELEMENT_PROFILER_H__ 00030 #define __NV_ELEMENT_PROFILER_H__ 00031 00032 #include <iostream> 00033 #include <pthread.h> 00034 #include <map> 00035 #include <stdint.h> 00036 #include <sys/time.h> 00037 00038 /** 00039 * 00040 * @c %NvElementProfiler is a helper class for profiling the performance of individual 00041 * elements. 00042 * 00043 * NvElementProfiler currently measures processing latencies, average processing rate and 00044 * number of units which arrived late at the element. This should be used internally 00045 * by the components. 00046 * 00047 * Components should call startProcessing() to indicate that a unit has been submitted 00048 * for processing and finishProcessing() to indicate that a unit has finished processing. 00049 * Components who do not require latency measurement need not call startProcessing(). 00050 * 00051 * Components can get data from NvElementProfiler using getProfilerData(). It 00052 * fills the #NvElementProfilerData structure. Components might not support all 00053 * the fields available in the strcuture and so a variable #valid_fields of 00054 * type #ProfilerField is also included in the structure. 00055 */ 00056 class NvElementProfiler { 00057 public: 00058 /** 00059 * Data type indicating valid fields in #NvElementProfilerData structure. 00060 */ 00061 typedef int ProfilerField; 00062 static const ProfilerField PROFILER_FIELD_NONE = 0; 00063 static const ProfilerField PROFILER_FIELD_TOTAL_UNITS = 1; 00064 static const ProfilerField PROFILER_FIELD_LATE_UNITS = 2; 00065 static const ProfilerField PROFILER_FIELD_LATENCIES = 4; 00066 static const ProfilerField PROFILER_FIELD_FPS = 8; 00067 static const ProfilerField PROFILER_FIELD_ALL = (PROFILER_FIELD_FPS << 1) - 1; 00068 00069 /** 00070 * Holds profiling data for the element. 00071 * 00072 * Some elements may not support all the fields in the structure. User should check 00073 * the valid_fields flag to check which fields are valid. 00074 */ 00075 typedef struct { 00076 /** Valid Fields which are supported by the element. */ 00077 ProfilerField valid_fields; 00078 00079 /** Average latency of all processed units, in microseconds. */ 00080 uint64_t average_latency_usec; 00081 /** Minimum of latencies for each processed units, in microseconds. */ 00082 uint64_t min_latency_usec; 00083 /** Maximum of latencies for each processed units, in microseconds. */ 00084 uint64_t max_latency_usec; 00085 00086 /** Total units processed. */ 00087 uint64_t total_processed_units; 00088 /** Number of units which arrived late at the element. */ 00089 uint64_t num_late_units; 00090 00091 /** Average rate at which the units were processed. */ 00092 float average_fps; 00093 00094 /** Total profiling time. */ 00095 struct timeval profiling_time; 00096 } NvElementProfilerData; 00097 00098 /** 00099 * Get the profiling data for the element. 00100 * 00101 * @param[out] data Reference to the NvElementProfilerData structure which should be filled. 00102 */ 00103 void getProfilerData(NvElementProfilerData &data); 00104 00105 /** 00106 * Print the element's profiling data to an output stream. 00107 * 00108 * @param[in] out_stream Reference to a std::ostream. 00109 */ 00110 void printProfilerData(std::ostream &out_stream = std::cout); 00111 00112 /** 00113 * Inform the profiler processing has started. 00114 * 00115 * Has no effect if profiler is disabled. 00116 * 00117 * @return ID of the unit, to be supplied with finishProcessing();. 00118 */ 00119 uint64_t startProcessing(); 00120 00121 /** 00122 * Inform the profiler processing has finished. 00123 * 00124 * Has no effect if profiler is disabled. 00125 * 00126 * @param[in] id ID of the unit whose processing is finished, 00127 * 0 if the first unit in the profiler's queue should be picked. 00128 * @param[in] is_late Should be true if the frame arrived late at the element. 00129 */ 00130 void finishProcessing(uint64_t id, bool is_late); 00131 00132 /** 00133 * Enable the profiler. 00134 * 00135 * startProcessing() and finishProcessing() will not have any effect till the profiler is enabled. 00136 * 00137 * @param[in] reset_data Reset the profiled data. 00138 */ 00139 void enableProfiling(bool reset_data); 00140 00141 /** 00142 * Disable the profiler. 00143 */ 00144 void disableProfiling(); 00145 private: 00146 /** 00147 * Reset the profiler data. 00148 */ 00149 void reset(); 00150 00151 pthread_mutex_t profiler_lock; /**< Mutex to synchronize multithreaded access to profiler data. */ 00152 00153 bool enabled; /**< Flag indicating if profiler is enabled. */ 00154 00155 const ProfilerField valid_fields; /**< Valid fields for the element. */ 00156 00157 struct NvElementProfilerDataInternal : NvElementProfilerData { 00158 /** Wall-clock time at which the first unit was processed. */ 00159 struct timeval start_time; 00160 00161 /** Wall-clock time at which the latest unit was processed. */ 00162 struct timeval stop_time; 00163 00164 /** Total accumulated time. 00165 * When performance measurement is restarted #start_time and #stop_time 00166 * will be reset. This field is used to accumulate time before 00167 * resetting. */ 00168 struct timeval accumulated_time; 00169 00170 /** Total accumulated latency for all units, in microseconds. */ 00171 uint64_t total_latency; 00172 } data_int; 00173 00174 /** Queue used to maintain the timestamps of when the unit 00175 * processing started. Required to calculate latency. */ 00176 std::map<uint64_t, struct timeval> unit_start_time_queue; 00177 00178 uint64_t unit_id_counter; /**< Unique ID of the last unit. */ 00179 00180 /** 00181 * Constructor for NvElementProfiler. 00182 * 00183 * Initializes internal data structures. The profiler is disabled by default. 00184 * @param fields 00185 */ 00186 NvElementProfiler(ProfilerField fields); 00187 00188 /** 00189 * Disallow copy constructor. 00190 */ 00191 NvElementProfiler(const NvElementProfiler& that); 00192 /** 00193 * Disallow assignment. 00194 */ 00195 void operator=(NvElementProfiler const&); 00196 00197 ~NvElementProfiler(); 00198 00199 friend class NvElement; 00200 }; 00201 00202 #endif