Program Listing for File AstPerformance.h

Program Listing for File AstPerformance.h#

Return to documentation for file (src/midend/astDiagnostics/AstPerformance.h)

// Author: Dan Quinlan
// $Id: AstPerformance.h,v 1.5 2008/01/25 19:53:30 dquinlan Exp $

#ifndef AST_PERFORMANCE_H
#define AST_PERFORMANCE_H

// #include <rose.h>

#include <string>
#include <vector>
#include <list>

#ifdef _MSC_VER
#include <time.h>
#endif

#include <assert.h>

#include "rosedll.h"

// Future Design:
//   1) Different levels of output
//   2) External file output (for more complete statistics)
//   3) A mechanism to report on hotspots, performance data, etc. ???

// namespace ROSE_Performance {
// This namespace represents the support for performance
// monitoring of the difference phases of processing
// within ROSE.

// using namespace std;

// DQ (2/20/2013): Change the type to support better timer from Liao.
// typedef clock_t RoseTimeType;
typedef double RoseTimeType;


class ROSE_MemoryUsage
   {

  // DQ (12/11/2006): Added simpler function than ramust mechanism, used for computing the memory in use.
  // long int getCurrentMemoryUsage(); // reported in Kilobytes.

  // JJW 1-25-2008: Added struct to allow only a single access to
  // /proc/self/statm, and to replace the STATM_CODE macro
     int memory_pages;
     int resident_pages;
     int shared_pages;
     int code_pages;
     int stack_pages;
     int library_pages;
     int dirty_pages;
     bool valid;
   public:
     ROSE_MemoryUsage(): memory_pages(0), resident_pages(0), shared_pages(0),
                         code_pages(0), stack_pages(0), library_pages(0),
                         dirty_pages(0) {
       valid = getStatmInfo();
     }

     bool informationValid() const {return valid;}

   private:
     bool getStatmInfo();

  // DQ (12/12/2006): Supporting functions (available from reading /proc/<pid>/statm file).
   public:
     int getPageSizeBytes() const;
     int getAvailableMemoryPages() const;
     int getNumberOfResidentPages() const;
     int getNumberOfSharedPages() const;
     int getNumberOfCodePages() const;
     int getNumberOfStackPages() const;
     int getNumberOfLibraryPages() const;
     int getNumberOfDirtyPages() const;

     int getNumberOfCodePlusLibraryPages() const;
     long getMemoryUsageKilobytes() const;

     double getPageSizeMegabytes() const;
     double getAvailableMemoryMegabytes() const;
     double getNumberOfResidentMegabytes() const;
     double getNumberOfSharedMegabytes() const;
     double getNumberOfCodeMegabytes() const;
     double getNumberOfStackMegabytes() const;
     double getNumberOfLibraryMegabytes() const;
     double getNumberOfDirtyMegabytes() const;

     double getNumberOfCodePlusLibraryMegabytes() const;
     double getMemoryUsageMegabytes() const;
   };


class ProcessingPhase
   {
  // This class stores a string and a final number to record the performance.

     protected:
          std::string name;
          double performance;
          double resolution;
          ROSE_MemoryUsage memoryUsage;

#if 0
       // DQ (12/8/2006): Mechanism based on RAMUST (which is problematic)
          unsigned long internalMemoryUsageData;
#else
       // DQ (12/11/2006): Mechanism based on PetSc implementation (used in Overture).
          double internalMemoryUsageData;
#endif
       // Permit a hierarchy of performance monitors
          std::vector<ProcessingPhase*> childList;

     public:
          ProcessingPhase ();
          ProcessingPhase ( const std::string & s, double p, ProcessingPhase *parent );

       // DQ (7/21/2010): We need a destructor so that we can set the internalMemoryUsageData
       // in the destructor instead of the constructor.  This way the memory usage is for the
       // operation that is being evaluated instead of the memory usage just before the
       // operation being evaluated.
          virtual ~ProcessingPhase();

          void outputReport ( int n );
          void outputReportToFile ( std::ofstream & datafile );
          void outputReportHeaderToFile ( std::ofstream & datafile );

          void stopTiming(const RoseTimeType& timer);
          static double getCurrentDelta(const RoseTimeType& timer);

       // DQ (9/1/2006): These are defined in the class because
       // timer functions should have the lowest possible overhead.
          std::string get_name() const { return name; }
          void   set_name ( std::string & s) { name = s; }
          double get_performance() const { return performance; }
          void   set_performance (const double & p) { performance = p; }
          double get_resolution() const { return resolution; }
          void   set_resolution (const double & r) { resolution = r; }
#if 0
          unsigned long get_memory_usage() const { return internalMemoryUsageData; }
          void   set_memory_usage (const unsigned long & m) { internalMemoryUsageData = m; }
#else
          double get_memory_usage() const { return internalMemoryUsageData; }
          void   set_memory_usage (const double & m) { internalMemoryUsageData = m; }
#endif
   };

// Forward reference required from "void AstPerformance::generateReportToFile(SgProject*);"
class SgProject;

class ROSE_DLL_API AstPerformance
   {
     public:
       // DQ (9/1/2006): Note that we don't have the project yet when this is called within "main()" to summarize the total time.
          AstPerformance ( std::string s , bool outputReport = false );
          virtual ~AstPerformance();

       // This is the evolving data (built locally so that parents in the hierarchy can refer to it)
          ProcessingPhase* localData;

       // DQ (10/28/2020): Adding control over output of performance report.
          static bool outputCompilationPerformance;

       // DQ (9/1/2006): Moved to the base class.
       // Use the Linux timer to provide nanosecond resolution
       // JJW (5/21/2008): Changed back to clock(3) for portability

          std::string label;
          static SgProject* project;

          static void set_project(SgProject* projectParameter);

          bool outputReportInDestructor;

          void generateReportFromObject() const;
          void generateReportToFile( SgProject* project ) const;
          static void generateReport();

       // virtual double performanceResolution();
          static double performanceResolution();

       // Support for file locking (so that the performance file is not
       // corrupted by parallel writes as used in parallel compiles with
       // the "-j#" make option).
          static int getLock();
          static void releaseLock (int fd );

       // Timer function support
          static void reportAccumulatedTime ( const std::string & s, const double & accumulatedTime, const double & numberFunctionCalls );

          static void startTimer ( RoseTimeType & time );
          static void accumulateTime ( RoseTimeType & startTime, double & accumulatedTime, double & numberFunctionCalls );

     protected:
       // Storage of all performance information about
       // processing phases saved here for later processing.
          static std::vector<ProcessingPhase*> data;

       // This allows any existing performance monitor to become
       // the parent of any child performance monitor
          static std::list<AstPerformance*> performanceStack;
   };

// Base class for event tracing.  This class holds state related to
// the output stream and methods for emitting trace events.  It is
// separate from the TimingPerformance class so that we can have a
// TraceOnlyPerformance object that performs the same timing role, but
// does not record the timer in the performance stack.  This is useful
// for tracing frequently made calls without causing the report to get
// huge.
class ROSE_DLL_API TracingPerformance
  {
  protected:
  // MS (11/9/2020): tracing related fields
  static std::ofstream *trace_stream;
  static double trace_zero_time;
  static bool first_event;
  static bool trace_durations;

  // private tracing functions.  these are private since they are only
  // called from within the destructor
  void emitTraceDurationEvent ( std::string label, double t, double dur );
  void emitTraceBoundaryEvent ( std::string label, double t, bool isStart );
  bool checkTracing ( );

  public:
  TracingPerformance() { }
  };

// MS (11/27/2020) TraceOnlyPerformance has the same API as
// TimingPerformance, but does not derive from AstPerformance and thus
// does not interfere with the performance reporting facility.
class ROSE_DLL_API TraceOnlyPerformance : public TracingPerformance
{
 private:
  RoseTimeType timer;
  std::string label;

 public:
  TraceOnlyPerformance ( std::string s , bool outputReport = false );
  virtual ~TraceOnlyPerformance();
  void endTimer();
  typedef RoseTimeType time_type;
};

class ROSE_DLL_API TimingPerformance :
  public AstPerformance, public TracingPerformance
   {
     private:
          RoseTimeType timer;

  // Used for timing compilation within ROSE
     public:
          TimingPerformance ( std::string s , bool outputReport = false );
          virtual ~TimingPerformance();

       // DQ (6/30/2013): Refactored this function to be something that can be called from the
       // destructor and also in the scope of the outer most scope timer before report generation
       // (so we can compute total elapsed time).
          void endTimer();

       // virtual double performanceResolution();
          static double performanceResolution();

          typedef RoseTimeType time_type; // For compatibility
   };

// comment out use of namespace
// }

#endif