fixed: auto_ptr -> unique_ptr
[opensg.git] / Source / Base / PerfMonitor / OSGPerfMonitor.h
blob07a1a32977cbe9b061a45385b273fad16ab3bcca
1 /*---------------------------------------------------------------------------*\
2 * OpenSG *
3 * *
4 * *
5 * Copyright (C) 2000-2006 by the OpenSG Forum *
6 * *
7 * www.opensg.org *
8 * *
9 * contact: dirk@opensg.org, gerrit.voss@vossg.org, jbehr@zgdv.de *
10 * *
11 \*---------------------------------------------------------------------------*/
12 /*---------------------------------------------------------------------------*\
13 * License *
14 * *
15 * This library is free software; you can redistribute it and/or modify it *
16 * under the terms of the GNU Library General Public License as published *
17 * by the Free Software Foundation, version 2. *
18 * *
19 * This library is distributed in the hope that it will be useful, but *
20 * WITHOUT ANY WARRANTY; without even the implied warranty of *
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
22 * Library General Public License for more details. *
23 * *
24 * You should have received a copy of the GNU Library General Public *
25 * License along with this library; if not, write to the Free Software *
26 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
27 * *
28 \*---------------------------------------------------------------------------*/
29 /*---------------------------------------------------------------------------*\
30 * Changes *
31 * *
32 * *
33 * *
34 * *
35 * *
36 * *
37 \*---------------------------------------------------------------------------*/
39 #ifndef _OSG_PERF_MONITOR_
40 #define _OSG_PERF_MONITOR_
42 #include "OSGConfig.h"
43 #include "OSGBaseDef.h"
45 #include "OSGTime.h"
46 #include "OSGConfig.h"
47 #include "OSGSingletonHolder.h"
48 #include "OSGLock.h"
50 #include <boost/shared_ptr.hpp>
52 #include <deque>
53 #include <vector>
54 #include <string>
55 #include <numeric>
56 #include <iostream>
58 #include "OSGDeprecatedCPP.h"
60 OSG_BEGIN_NAMESPACE
62 class NestedSampleInfo;
63 typedef boost::shared_ptr<NestedSampleInfo> NestedSampleInfoPtr;
65 /*! \ingroup BaseGrpPerfMon
66 * \nohierarchy
67 * Helper class to hold samples and sub samples.
68 * A node in the "performance tree".
70 class OSG_BASE_DLLMAPPING NestedSampleInfo
72 public:
73 #ifdef OSG_STL_HAS_HASH_MAP
74 #if !defined(WIN32) && !defined(_LIBCPP_VERSION)
75 /*! \nohierarchy */
76 struct string_hash
78 size_t operator()(const std::string &s) const
80 return OSG_STDEXTENSION_NAMESPACE::__stl_hash_string(s.c_str());
84 typedef OSG_STDEXTENSION_NAMESPACE::hash_map<std::string, NestedSampleInfoPtr,string_hash> subsample_map_t;
85 #else
86 typedef OSG_STDEXTENSION_NAMESPACE::hash_map<std::string, NestedSampleInfoPtr> subsample_map_t;
87 #endif
88 #else
89 typedef std::map<std::string, NestedSampleInfoPtr> subsample_map_t;
90 #endif
91 typedef std::deque<Real32> sample_list_t;
92 typedef std::vector<Real32> sample_vector_t;
94 NestedSampleInfo(const std::string& name)
95 : mName(name)
96 , mSubSamples()
97 , mTimeSummer(0)
98 , mSamples()
99 , mPctSamples()
100 , mStartTime(0)
101 , mMax(0.0)
102 , mAverage(0.0)
103 , mPercentage(0.0)
106 static NestedSampleInfoPtr create(const std::string& name)
108 return NestedSampleInfoPtr(new NestedSampleInfo(name));
111 void start()
113 mStartTime = OSG::getTimeStamp();
115 void stop()
117 OSG::TimeStamp stop_time(OSG::getTimeStamp());
118 OSG::TimeStamp sample_time(stop_time - mStartTime);
119 addTime(OSG::getTimeStampMsecs(sample_time));
122 void addTime(Real32 sample)
124 mTimeSummer += sample;
127 /** Update all our internal values and the settings of children. */
128 void updateFrame();
131 * Helper to recalculate the percentage given the average of the parent.
133 void calcPercentage(const Real32 parentAverage);
136 * "print" the details of this sample and its children to a string that
137 * is returned.
139 std::string outString(UInt32 indent=0, bool detailed=false);
141 // -- Accessors -- //
142 sample_vector_t getSamples() const
144 return sample_vector_t(mSamples.begin(), mSamples.end());
146 sample_vector_t getPercentageSamples() const
148 return sample_vector_t(mPctSamples.begin(), mPctSamples.end());
150 const std::string& getName() const
152 return mName;
154 Real32 getAverage() const
156 return mAverage;
158 Real32 getPercentage() const
160 return mPercentage;
163 public:
164 std::string mName; /**< Name of the sample. */
165 subsample_map_t mSubSamples; /**< Other sample infos below us. map: name --> NestedSampleInfoPtr */
166 Real32 mTimeSummer; /**< Running time summer. Moved to samples once per frame. */
167 sample_list_t mSamples; /**< List of samples we have collected. */
168 sample_list_t mPctSamples; /**< List of percentage samples we have collected. (running list of percentages) */
169 OSG::TimeStamp mStartTime; /**< The last start time we tried. */
170 Real32 mMax; /**< The maximum sample. */
171 Real32 mAverage; /**< Average time in seconds. */
172 Real32 mPercentage; /**< Percentage of time consumed relative to siblings. */
175 /*! \ingroup GrpBasePerfMon
176 * \nohierarchy
177 * Performance tracker that tracks the performance of nested calls. This is
178 * useful for later visualization of the performance from these values.
180 class OSG_BASE_DLLMAPPING NestedPerfTracker
182 public:
183 /*! \nohierarchy */
184 class SamplePair
186 public:
187 SamplePair(UInt32 depth_, NestedSampleInfoPtr sample_)
188 : depth(depth_)
189 , sample(sample_)
193 bool operator==(const SamplePair& rhs) const
195 return depth == rhs.depth && sample == rhs.sample;
198 UInt32 depth;
199 NestedSampleInfoPtr sample;
202 typedef std::vector<NestedSampleInfoPtr> sample_stack_t;
203 typedef std::deque<Real32> frame_times_list_t;
204 typedef std::vector<Real32> frame_times_vector_t;
205 typedef std::vector<SamplePair> sample_pair_vector_t;
207 protected:
208 template <class SingletonT>
209 friend class OSG::SingletonHolder;
211 NestedPerfTracker()
212 : mPerfRoot()
213 , mEnabled(false)
214 , mCurSampleStack()
215 , mLastFrameStart(OSG::getTimeStamp())
216 , mFrameTimes()
217 , mFrameRate(0.0)
219 mPerfRoot = NestedSampleInfo::create("root");
220 mCurSampleStack.push_back(mPerfRoot);
223 public:
224 void enable(bool val = true)
226 mEnabled = val;
229 void enter(const std::string& name)
231 if(! mEnabled)
233 return;
236 // Get the current sample we are in and then get it's subsample for
237 // the new entry
238 NestedSampleInfoPtr cur_sample = mCurSampleStack.back();
239 if(cur_sample->mSubSamples.find(name) == cur_sample->mSubSamples.end())
241 cur_sample->mSubSamples[name] = NestedSampleInfo::create(name);
243 NestedSampleInfoPtr sub_sample = cur_sample->mSubSamples[name];
245 // Start the time and append it to the back of the stack
246 sub_sample->start();
247 mCurSampleStack.push_back(sub_sample);
250 void exit(const std::string& name)
252 if(! mEnabled)
254 return;
257 NestedSampleInfoPtr cur_sample = mCurSampleStack.back();
258 OSG_ASSERT(mCurSampleStack.size() > 1);
259 cur_sample->stop();
260 mCurSampleStack.pop_back();
264 * Helper method to add a sampled time without using enter and exit.
265 * This is useful when we have data from another source and just want to
266 * add it.
268 void addSampledTime(const std::string& name, Real32 timeVal)
270 if(! mEnabled)
272 return;
275 // Get the current sample we are in and then get it's subsample for
276 // the new entry
277 NestedSampleInfoPtr cur_sample = mCurSampleStack.back();
278 if(! cur_sample->mSubSamples.count(name))
280 cur_sample->mSubSamples[name] = NestedSampleInfo::create(name);
282 NestedSampleInfoPtr sub_sample = cur_sample->mSubSamples[name];
283 sub_sample->addTime(timeVal);
287 * Update the periodic performance information such as percentages
288 * and anything else that we can calculate continuously.
290 void updateFrame();
292 /** "print" the details of this all samples in the tree to a string. */
293 std::string outString(bool detailed=false);
296 * Return a flat tree of sample nodes.
297 * [(depth,sample), ...]
299 sample_pair_vector_t getFlatSampleTree(
300 UInt32 depth = 0,
301 NestedSampleInfoPtr curNode = NestedSampleInfoPtr()
304 // --- Accessors --- //
305 bool getEnabled() const
307 return mEnabled;
311 * Return the average frame rate.
313 * @param avgOverFrames If 0, then over all frames we know about.
315 Real32 getFrameRate(UInt32 avgOverFrames = 0) const;
317 frame_times_vector_t getFrameTimes() const
319 return frame_times_vector_t(mFrameTimes.begin(), mFrameTimes.end());
322 UInt32 getMaxSamples() const
324 return max_samples;
327 public:
328 NestedSampleInfoPtr mPerfRoot;
329 bool mEnabled;
330 sample_stack_t mCurSampleStack;
331 OSG::TimeStamp mLastFrameStart;
332 frame_times_list_t mFrameTimes;
333 Real32 mFrameRate;
335 static UInt32 max_samples; /**<< The maximum number of samples to collect. */
339 /*! \ingroup GrpBasePerfMon
340 * \nohierarchy
341 * Central class for all performance monitoring.
342 * This class is a singleton that provides the interface for collecting
343 * performance monitoring data. It makes use of other helper classes to
344 * aggregate and analyze this data as needed.
346 * @note Samples are collected per thread, but in order to reduce sampling
347 * overhead (ie locking), we do not extend the list of available threads
348 * on each sample. Instead, we only update the potential thread list
349 * once per frame. If a new thread is detected, it is added to a new
350 * thread list that is cleared as part of the frame update.
352 * File format:
353 * One line per sample. Each list is a list of comma separated values.
354 * <thread id: int>,<timestamp: double>,<type: int>,<metric: double>,<name:"string",<desc: "string">
356 class OSG_BASE_DLLMAPPING PerfMonitorBase
358 public:
359 enum SampleType
361 ENTER = 0, /**< Enter a region. */
362 EXIT = 1, /**< Exit a region. */
363 MARK = 10, /**< Mark point for something interesting. */
364 METRIC = 11, /**< Store a metric value. */
365 FRAME = 100, /**< Store marker for the end/start of a frame. */
366 LAST
369 /*! \nohierarchy
370 Data for a single sample.
372 struct SampleData
374 SampleData(OSG::UInt64 tid, OSG::Real64 rTimestamp,
375 SampleType eType, const std::string& szName,
376 OSG::Real32 metricValue = 0.0,
377 const std::string& szDesc = "")
378 : thread_id(tid)
379 , timestamp(rTimestamp)
380 , type(eType)
381 , metric_value(metricValue)
382 , name(szName)
383 , desc(szDesc)
387 bool operator==(const SampleData& rhs) const
389 return ( (rhs.thread_id == thread_id) &&
390 (rhs.timestamp == timestamp) &&
391 (rhs.type == type) &&
392 (rhs.metric_value == metric_value) &&
393 (rhs.desc == desc) &&
394 (rhs.name == name));
397 OSG::UInt64 thread_id; /**< unique id of the thread for the sample. */
398 OSG::Real64 timestamp; /**< timestamp when the sample occured. */
399 SampleType type; /**< The type of sample collected. */
400 OSG::Real32 metric_value; /**< Value of any metric collected. */
401 std::string name; /**< Name for the sample. */
402 std::string desc; /**< Extended description of the sample. */
405 typedef std::vector<SampleData> sample_data_list_t;
407 protected:
408 template <class SingletonT>
409 friend class OSG::SingletonHolder;
411 PerfMonitorBase();
412 ~PerfMonitorBase(void);
414 private:
416 PerfMonitorBase(const PerfMonitorBase &other);
417 void operator =(const PerfMonitorBase&rhs);
419 public:
420 /** Reset the performance collection. */
421 void reset();
423 void enable(bool val = true);
426 * Enter a sample for the performance monitor.
427 * @arg sampleType: The type of sample that we should add.
428 * @arg desc: A text description (name, label, etc) to go with the sample.
430 void sample(SampleType sampleType, const std::string& name,
431 OSG::Real32 metricValue = 0.0, const std::string& desc = "");
433 /** Called once per "frame" to update internal data structures. */
434 void updateFrame();
436 // --- Accessors --- //
437 bool getEnabled() const
439 return mEnabled;
442 /** Return the id of the current thread. */
443 OSG::UInt64 getThreadId() const;
445 OSG::Real64 getTimeStampMs()
447 return OSG::getTimeStampMsecs(OSG::getTimeStamp()) - mStartTimeMs;
450 // --- Output Processing --- //
451 /** Set the output file to use for data dumping. */
452 void setOutputFile(const std::string& filename);
454 /** Set the output file flush rate. */
455 void setOutputFlushRate(OSG::UInt64 rate)
457 mFlushingRate = rate;
460 /** Periodically called to flush the output file. */
461 void flushOutput();
463 /** Helper to print samples to std::out. */
464 void printSamples();
466 public:
467 bool mEnabled; /**< Indicates that the performance monitor should be active. */
468 sample_data_list_t mSamples; /**< Samples collected for all known threads. */
470 /** Must be acquired if updating the data structure of any shared resource. */
471 OSG::LockRefPtr mDataLock;
473 /** Data flushing. */
474 OSG::UInt64 mCurrentFrameNum; /**< The current frame number. */
475 OSG::Real64 mStartTimeMs; /**< The start time for the system in milliseconds. */
476 OSG::UInt64 mFlushingRate; /**< Number of frames between data flushes. */
477 std::ofstream* mOutFile; /**< The output file to use. */
480 #if defined(WIN32)
481 OSG_BASE_EXPIMP_TMPL
482 template class OSG_BASE_DLLMAPPING SingletonHolder<PerfMonitorBase>;
483 #endif
485 typedef SingletonHolder<PerfMonitorBase> PerfMonitor;
488 OSG_END_NAMESPACE
490 #endif