changed: auto add updateData callback to stages so that stagedata can be updated...
[opensg.git] / Source / Base / PerfMonitor / OSGPerfMonitor.h
blob5745d84b089ad1899b73fee29ee903b42cf917bc
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 #ifndef WIN32
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 , mTimeSummer(0)
97 , mStartTime(0)
98 , mMax(0.0)
99 , mAverage(0.0)
100 , mPercentage(0.0)
103 static NestedSampleInfoPtr create(const std::string& name)
105 return NestedSampleInfoPtr(new NestedSampleInfo(name));
108 void start()
110 mStartTime = OSG::getTimeStamp();
112 void stop()
114 OSG::TimeStamp stop_time(OSG::getTimeStamp());
115 OSG::TimeStamp sample_time(stop_time - mStartTime);
116 addTime(OSG::getTimeStampMsecs(sample_time));
119 void addTime(Real32 sample)
121 mTimeSummer += sample;
124 /** Update all our internal values and the settings of children. */
125 void updateFrame();
128 * Helper to recalculate the percentage given the average of the parent.
130 void calcPercentage(const Real32 parentAverage);
133 * "print" the details of this sample and its children to a string that
134 * is returned.
136 std::string outString(UInt32 indent=0, bool detailed=false);
138 // -- Accessors -- //
139 sample_vector_t getSamples() const
141 return sample_vector_t(mSamples.begin(), mSamples.end());
143 sample_vector_t getPercentageSamples() const
145 return sample_vector_t(mPctSamples.begin(), mPctSamples.end());
147 const std::string& getName() const
149 return mName;
151 Real32 getAverage() const
153 return mAverage;
155 Real32 getPercentage() const
157 return mPercentage;
160 public:
161 std::string mName; /**< Name of the sample. */
162 subsample_map_t mSubSamples; /**< Other sample infos below us. map: name --> NestedSampleInfoPtr */
163 Real32 mTimeSummer; /**< Running time summer. Moved to samples once per frame. */
164 sample_list_t mSamples; /**< List of samples we have collected. */
165 sample_list_t mPctSamples; /**< List of percentage samples we have collected. (running list of percentages) */
166 OSG::TimeStamp mStartTime; /**< The last start time we tried. */
167 Real32 mMax; /**< The maximum sample. */
168 Real32 mAverage; /**< Average time in seconds. */
169 Real32 mPercentage; /**< Percentage of time consumed relative to siblings. */
172 /*! \ingroup GrpBasePerfMon
173 * \nohierarchy
174 * Performance tracker that tracks the performance of nested calls. This is
175 * useful for later visualization of the performance from these values.
177 class OSG_BASE_DLLMAPPING NestedPerfTracker
179 public:
180 /*! \nohierarchy */
181 class SamplePair
183 public:
184 SamplePair(UInt32 depth_, NestedSampleInfoPtr sample_)
185 : depth(depth_)
186 , sample(sample_)
190 bool operator==(const SamplePair& rhs) const
192 return depth == rhs.depth && sample == rhs.sample;
195 UInt32 depth;
196 NestedSampleInfoPtr sample;
199 typedef std::vector<NestedSampleInfoPtr> sample_stack_t;
200 typedef std::deque<Real32> frame_times_list_t;
201 typedef std::vector<Real32> frame_times_vector_t;
202 typedef std::vector<SamplePair> sample_pair_vector_t;
204 protected:
205 template <class SingletonT>
206 friend class OSG::SingletonHolder;
208 NestedPerfTracker()
209 : mEnabled(false)
210 , mLastFrameStart(OSG::getTimeStamp())
211 , mFrameRate(0.0)
213 mPerfRoot = NestedSampleInfo::create("root");
214 mCurSampleStack.push_back(mPerfRoot);
217 public:
218 void enable(bool val = true)
220 mEnabled = val;
223 void enter(const std::string& name)
225 if(! mEnabled)
227 return;
230 // Get the current sample we are in and then get it's subsample for
231 // the new entry
232 NestedSampleInfoPtr cur_sample = mCurSampleStack.back();
233 if(cur_sample->mSubSamples.find(name) == cur_sample->mSubSamples.end())
235 cur_sample->mSubSamples[name] = NestedSampleInfo::create(name);
237 NestedSampleInfoPtr sub_sample = cur_sample->mSubSamples[name];
239 // Start the time and append it to the back of the stack
240 sub_sample->start();
241 mCurSampleStack.push_back(sub_sample);
244 void exit(const std::string& name)
246 if(! mEnabled)
248 return;
251 NestedSampleInfoPtr cur_sample = mCurSampleStack.back();
252 OSG_ASSERT(mCurSampleStack.size() > 1);
253 cur_sample->stop();
254 mCurSampleStack.pop_back();
258 * Helper method to add a sampled time without using enter and exit.
259 * This is useful when we have data from another source and just want to
260 * add it.
262 void addSampledTime(const std::string& name, Real32 timeVal)
264 if(! mEnabled)
266 return;
269 // Get the current sample we are in and then get it's subsample for
270 // the new entry
271 NestedSampleInfoPtr cur_sample = mCurSampleStack.back();
272 if(! cur_sample->mSubSamples.count(name))
274 cur_sample->mSubSamples[name] = NestedSampleInfo::create(name);
276 NestedSampleInfoPtr sub_sample = cur_sample->mSubSamples[name];
277 sub_sample->addTime(timeVal);
281 * Update the periodic performance information such as percentages
282 * and anything else that we can calculate continuously.
284 void updateFrame();
286 /** "print" the details of this all samples in the tree to a string. */
287 std::string outString(bool detailed=false);
290 * Return a flat tree of sample nodes.
291 * [(depth,sample), ...]
293 sample_pair_vector_t getFlatSampleTree(
294 UInt32 depth = 0,
295 NestedSampleInfoPtr curNode = NestedSampleInfoPtr()
298 // --- Accessors --- //
299 bool getEnabled() const
301 return mEnabled;
305 * Return the average frame rate.
307 * @param avgOverFrames If 0, then over all frames we know about.
309 Real32 getFrameRate(UInt32 avgOverFrames = 0) const;
311 frame_times_vector_t getFrameTimes() const
313 return frame_times_vector_t(mFrameTimes.begin(), mFrameTimes.end());
316 UInt32 getMaxSamples() const
318 return max_samples;
321 public:
322 NestedSampleInfoPtr mPerfRoot;
323 bool mEnabled;
324 sample_stack_t mCurSampleStack;
325 OSG::TimeStamp mLastFrameStart;
326 frame_times_list_t mFrameTimes;
327 Real32 mFrameRate;
329 static UInt32 max_samples; /**<< The maximum number of samples to collect. */
333 /*! \ingroup GrpBasePerfMon
334 * \nohierarchy
335 * Central class for all performance monitoring.
336 * This class is a singleton that provides the interface for collecting
337 * performance monitoring data. It makes use of other helper classes to
338 * aggregate and analyze this data as needed.
340 * @note Samples are collected per thread, but in order to reduce sampling
341 * overhead (ie locking), we do not extend the list of available threads
342 * on each sample. Instead, we only update the potential thread list
343 * once per frame. If a new thread is detected, it is added to a new
344 * thread list that is cleared as part of the frame update.
346 * File format:
347 * One line per sample. Each list is a list of comma separated values.
348 * <thread id: int>,<timestamp: double>,<type: int>,<metric: double>,<name:"string",<desc: "string">
350 class OSG_BASE_DLLMAPPING PerfMonitorBase
352 public:
353 enum SampleType
355 ENTER = 0, /**< Enter a region. */
356 EXIT = 1, /**< Exit a region. */
357 MARK = 10, /**< Mark point for something interesting. */
358 METRIC = 11, /**< Store a metric value. */
359 FRAME = 100, /**< Store marker for the end/start of a frame. */
360 LAST
363 /*! \nohierarchy
364 Data for a single sample.
366 struct SampleData
368 SampleData()
371 SampleData(OSG::UInt64 tid, OSG::Real64 timestamp,
372 SampleType type, const std::string& name,
373 OSG::Real32 metricValue = 0.0,
374 const std::string& desc = "")
375 : thread_id(tid)
376 , timestamp(timestamp)
377 , type(type)
378 , metric_value(metricValue)
379 , name(name)
380 , desc(desc)
384 bool operator==(const SampleData& rhs) const
386 return ( (rhs.thread_id == thread_id) &&
387 (rhs.timestamp == timestamp) &&
388 (rhs.type == type) &&
389 (rhs.metric_value == metric_value) &&
390 (rhs.desc == desc) &&
391 (rhs.name == name));
394 OSG::UInt64 thread_id; /**< unique id of the thread for the sample. */
395 OSG::Real64 timestamp; /**< timestamp when the sample occured. */
396 SampleType type; /**< The type of sample collected. */
397 OSG::Real32 metric_value; /**< Value of any metric collected. */
398 std::string name; /**< Name for the sample. */
399 std::string desc; /**< Extended description of the sample. */
402 typedef std::vector<SampleData> sample_data_list_t;
404 protected:
405 template <class SingletonT>
406 friend class OSG::SingletonHolder;
408 PerfMonitorBase();
409 ~PerfMonitorBase(void);
411 public:
412 /** Reset the performance collection. */
413 void reset();
415 void enable(bool val = true);
418 * Enter a sample for the performance monitor.
419 * @arg sampleType: The type of sample that we should add.
420 * @arg desc: A text description (name, label, etc) to go with the sample.
422 void sample(SampleType sampleType, const std::string& name,
423 OSG::Real32 metricValue = 0.0, const std::string& desc = "");
425 /** Called once per "frame" to update internal data structures. */
426 void updateFrame();
428 // --- Accessors --- //
429 bool getEnabled() const
431 return mEnabled;
434 /** Return the id of the current thread. */
435 OSG::UInt64 getThreadId() const;
437 OSG::Real64 getTimeStampMs()
439 return OSG::getTimeStampMsecs(OSG::getTimeStamp()) - mStartTimeMs;
442 // --- Output Processing --- //
443 /** Set the output file to use for data dumping. */
444 void setOutputFile(const std::string& filename);
446 /** Set the output file flush rate. */
447 void setOutputFlushRate(OSG::UInt64 rate)
449 mFlushingRate = rate;
452 /** Periodically called to flush the output file. */
453 void flushOutput();
455 /** Helper to print samples to std::out. */
456 void printSamples();
458 public:
459 bool mEnabled; /**< Indicates that the performance monitor should be active. */
460 sample_data_list_t mSamples; /**< Samples collected for all known threads. */
462 /** Must be acquired if updating the data structure of any shared resource. */
463 OSG::LockRefPtr mDataLock;
465 /** Data flushing. */
466 OSG::UInt64 mCurrentFrameNum; /**< The current frame number. */
467 OSG::Real64 mStartTimeMs; /**< The start time for the system in milliseconds. */
468 OSG::UInt64 mFlushingRate; /**< Number of frames between data flushes. */
469 std::ofstream* mOutFile; /**< The output file to use. */
472 #if defined(WIN32)
473 OSG_BASE_EXPIMP_TMPL
474 template class OSG_BASE_DLLMAPPING SingletonHolder<PerfMonitorBase>;
475 #endif
477 typedef SingletonHolder<PerfMonitorBase> PerfMonitor;
480 OSG_END_NAMESPACE
482 #endif