Program Listing for File Profiler.h

Return to documentation for file (src/ompl/tools/debug/Profiler.h)

/*********************************************************************
* Software License Agreement (BSD License)
*
*  Copyright (c) 2008, Willow Garage, Inc.
*  All rights reserved.
*
*  Redistribution and use in source and binary forms, with or without
*  modification, are permitted provided that the following conditions
*  are met:
*
*   * Redistributions of source code must retain the above copyright
*     notice, this list of conditions and the following disclaimer.
*   * Redistributions in binary form must reproduce the above
*     copyright notice, this list of conditions and the following
*     disclaimer in the documentation and/or other materials provided
*     with the distribution.
*   * Neither the name of the Willow Garage nor the names of its
*     contributors may be used to endorse or promote products derived
*     from this software without specific prior written permission.
*
*  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
*  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
*  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
*  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
*  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
*  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
*  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
*  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
*  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
*  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
*  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
*  POSSIBILITY OF SUCH DAMAGE.
*********************************************************************/

/* Author Ioan Sucan */

#ifndef OMPL_TOOLS_DEBUG_PROFILER_
#define OMPL_TOOLS_DEBUG_PROFILER_

#ifndef ENABLE_PROFILING

#ifdef NDEBUG
#define ENABLE_PROFILING 0
#else
#define ENABLE_PROFILING 1
#endif

#endif

#if ENABLE_PROFILING

#include <map>
#include <string>
#include <iostream>
#include <thread>
#include <mutex>

#include "ompl/util/Time.h"

namespace ompl
{
    namespace tools
    {
        class Profiler
        {
        public:
            // non-copyable
            Profiler(const Profiler &) = delete;
            Profiler &operator=(const Profiler &) = delete;

            class ScopedBlock
            {
            public:
                ScopedBlock(const std::string &name, Profiler &prof = Profiler::Instance()) : name_(name), prof_(prof)
                {
                    prof_.begin(name);
                }

                ~ScopedBlock()
                {
                    prof_.end(name_);
                }

            private:
                std::string name_;
                Profiler &prof_;
            };

            class ScopedStart
            {
            public:
                ScopedStart(Profiler &prof = Profiler::Instance()) : prof_(prof), wasRunning_(prof_.running())
                {
                    if (!wasRunning_)
                        prof_.start();
                }

                ~ScopedStart()
                {
                    if (!wasRunning_)
                        prof_.stop();
                }

            private:
                Profiler &prof_;
                bool wasRunning_;
            };

            static Profiler &Instance();

            Profiler(bool printOnDestroy = false, bool autoStart = false)
              : running_(false), printOnDestroy_(printOnDestroy)
            {
                if (autoStart)
                    start();
            }

            ~Profiler()
            {
                if (printOnDestroy_ && !data_.empty())
                    status();
            }

            static void Start()
            {
                Instance().start();
            }

            static void Stop()
            {
                Instance().stop();
            }

            static void Clear()
            {
                Instance().clear();
            }

            void start();

            void stop();

            void clear();

            static void Event(const std::string &name, const unsigned int times = 1)
            {
                Instance().event(name, times);
            }

            void event(const std::string &name, const unsigned int times = 1);

            static void Average(const std::string &name, const double value)
            {
                Instance().average(name, value);
            }

            void average(const std::string &name, const double value);

            static void Begin(const std::string &name)
            {
                Instance().begin(name);
            }

            static void End(const std::string &name)
            {
                Instance().end(name);
            }

            void begin(const std::string &name);

            void end(const std::string &name);

            static void Status(std::ostream &out = std::cout, bool merge = true)
            {
                Instance().status(out, merge);
            }

            void status(std::ostream &out = std::cout, bool merge = true);

            static void Console()
            {
                Instance().console();
            }

            void console();

            bool running() const
            {
                return running_;
            }

            static bool Running()
            {
                return Instance().running();
            }

        private:
            struct TimeInfo
            {
                TimeInfo()
                  : total(time::seconds(0.)), shortest(time::duration::max()), longest(time::duration::min()), parts(0)
                {
                }

                time::duration total;

                time::duration shortest;

                time::duration longest;

                unsigned long int parts;

                time::point start;

                void set()
                {
                    start = time::now();
                }

                void update()
                {
                    const time::duration &dt = time::now() - start;
                    if (dt > longest)
                        longest = dt;
                    if (dt < shortest)
                        shortest = dt;
                    total = total + dt;
                    ++parts;
                }
            };

            struct AvgInfo
            {
                double total;

                double totalSqr;

                unsigned long int parts;
            };

            struct PerThread
            {
                std::map<std::string, unsigned long int> events;

                std::map<std::string, AvgInfo> avg;

                std::map<std::string, TimeInfo> time;
            };

            void printThreadInfo(std::ostream &out, const PerThread &data);

            std::mutex lock_;
            std::map<std::thread::id, PerThread> data_;
            TimeInfo tinfo_;
            bool running_;
            bool printOnDestroy_;
        };
    }
}

#else

#include <string>
#include <iostream>

/* If profiling is disabled, provide empty implementations for the
   public functions */
namespace ompl
{
    namespace tools
    {
        class Profiler
        {
        public:
            class ScopedBlock
            {
            public:
                ScopedBlock(const std::string &, Profiler & = Profiler::Instance())
                {
                }

                ~ScopedBlock() = default;
            };

            class ScopedStart
            {
            public:
                ScopedStart(Profiler & = Profiler::Instance())
                {
                }

                ~ScopedStart() = default;
            };

            static Profiler &Instance();

            Profiler(bool = true, bool = true)
            {
            }

            ~Profiler() = default;

            static void Start()
            {
            }

            static void Stop()
            {
            }

            static void Clear()
            {
            }

            void start()
            {
            }

            void stop()
            {
            }

            void clear()
            {
            }

            static void Event(const std::string &, const unsigned int = 1)
            {
            }

            void event(const std::string &, const unsigned int = 1)
            {
            }

            static void Average(const std::string &, const double)
            {
            }

            void average(const std::string &, const double)
            {
            }

            static void Begin(const std::string &)
            {
            }

            static void End(const std::string &)
            {
            }

            void begin(const std::string &)
            {
            }

            void end(const std::string &)
            {
            }

            static void Status(std::ostream & = std::cout, bool = true)
            {
            }

            void status(std::ostream & = std::cout, bool = true)
            {
            }

            static void Console()
            {
            }

            void console()
            {
            }

            bool running() const
            {
                return false;
            }

            static bool Running()
            {
                return false;
            }
        };
    }
}

#endif

#endif