Resource Tracking for FlightGear: Difference between revisions

Jump to navigation Jump to search
m
Line 276: Line 276:
Here's a first stab at a simple subsystem to monitor FlightGear memory usage on Linux at 5 second intervals, consider it a "proof of concept" prototype now, as this would need to be cleaned up and implemented for Mac/Windows respectively - on Linux it simply works such that it merely fopen()s /proc/pid/smaps and copies two metrics to the property tree:
Here's a first stab at a simple subsystem to monitor FlightGear memory usage on Linux at 5 second intervals, consider it a "proof of concept" prototype now, as this would need to be cleaned up and implemented for Mac/Windows respectively - on Linux it simply works such that it merely fopen()s /proc/pid/smaps and copies two metrics to the property tree:
<syntaxhighlight lang="diff">
<syntaxhighlight lang="diff">
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 4808f9d..5b45fa6 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -194,6 +194,7 @@ option(ENABLE_TESTS      "Set to ON to build test applications (default)" ON)
option(ENABLE_FGCOM      "Set to ON to build the FGCom application (default)" ON)
option(ENABLE_FLITE      "Set to ON to build the Flite text-to-speech module" ON)
option(ENABLE_QT        "Set to ON to build the internal Qt launcher" ON)
+#option(ENABLE_SIGAR      "Set to ON to build with SIGAR support (experimental)" OFF)
if(LOGGING)
    # nothing
@@ -328,6 +329,13 @@ if(ENABLE_PROFILE)
    message(STATUS "Built-in profiler using gperftools available")
endif()
+if(ENABLE_SIGAR)
+    # find_package(SIGAR REQUIRED)
+    set(FG_HAVE_SIGAR 1)
+    message(STATUS "Built-in process monitoring using SIGAR available")
+endif(ENABLE_SIGAR)
+
+
if(ENABLE_RTI)
    message(STATUS "RTI: ENABLED")
    find_package(RTI)
diff --git a/CMakeModules/FindSIGAR.cmake b/CMakeModules/FindSIGAR.cmake
new file mode 100644
index 0000000..4c890a7
--- /dev/null
+++ b/CMakeModules/FindSIGAR.cmake
@@ -0,0 +1,52 @@
+# - Find SIGAR: https://support.hyperic.com/display/SIGAR/Home
+# Find the native SIGAR includes and library
+#
+#  SIGAR_INCLUDE_DIR - where to find SIGAR.h, etc.
+#  SIGAR_LIBRARIES  - List of libraries when using SIGAR.
+#  SIGAR_FOUND      - True if SIGAR found.
+#
+# Redistribution and use is allowed according to the terms of the BSD license.
+# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
+
+
+if (SIGAR_INCLUDE_DIR)
+  # Already in cache, be silent
+  set(SIGAR_FIND_QUIETLY TRUE)
+endif ()
+
+find_path(SIGAR_INCLUDE_DIR sigar.h
+  /opt/local/include
+  /usr/local/include
+  /usr/include
+)
+
+# SIGAR support a lot more platforms than listed here.
+# cf. sigar.hyperic.com
+set(SIGAR_NAMES sigar-x86-linux sigar-x86_64-linux sigar-amd64-linux sigar-universal-macosx sigar)
+find_library(SIGAR_LIBRARY
+  NAMES ${SIGAR_NAMES}
+  PATHS /usr/lib /usr/local/lib /opt/local/lib
+)
+
+if (SIGAR_INCLUDE_DIR AND SIGAR_LIBRARY)
+  set(SIGAR_FOUND TRUE)
+  set(SIGAR_LIBRARIES ${SIGAR_LIBRARY} ${CMAKE_DL_LIBS})
+else ()
+  set(SIGAR_FOUND FALSE)
+  set(SIGAR_LIBRARIES)
+endif ()
+
+if (SIGAR_FOUND)
+  message(STATUS "Found SIGAR: ${SIGAR_LIBRARIES}")
+else ()
+  message(STATUS "Not Found SIGAR: ${SIGAR_LIBRARY}")
+  if (SIGAR_FIND_REQUIRED)
+    message(STATUS "Looked for SIGAR libraries named ${SIGAR_NAMES}.")
+    message(FATAL_ERROR "Could NOT find SIGAR library")
+  endif ()
+endif ()
+
+mark_as_advanced(
+  SIGAR_LIBRARY
+  SIGAR_INCLUDE_DIR
+)
diff --git a/src/Main/CMakeLists.txt b/src/Main/CMakeLists.txt
diff --git a/src/Main/CMakeLists.txt b/src/Main/CMakeLists.txt
index 4b6926e..31d3a8f 100644
index 4b6926e..31d3a8f 100644
Line 319: Line 403:
   
   
diff --git a/src/Main/fg_init.cxx b/src/Main/fg_init.cxx
diff --git a/src/Main/fg_init.cxx b/src/Main/fg_init.cxx
index 30ffa0e..5548f76 100644
index 30ffa0e..ae936ab 100644
--- a/src/Main/fg_init.cxx
--- a/src/Main/fg_init.cxx
+++ b/src/Main/fg_init.cxx
+++ b/src/Main/fg_init.cxx
Line 335: Line 419:
   
   
+    ////////////////////////////////////////////////////////////////////
+    ////////////////////////////////////////////////////////////////////
+    // Add the ram usage statistics system
+    // Add the RAM/VRAM utilization statistics system (SIGAR)
+    ////////////////////////////////////////////////////////////////////
+    ////////////////////////////////////////////////////////////////////
+    globals->add_subsystem("memory-stats", new MemoryUsageStats, SGSubsystemMgr::INIT, 5.00);
+    globals->add_subsystem("process-stats", new MemoryUsageStats, SGSubsystemMgr::INIT, 1.00);
   
   
     ////////////////////////////////////////////////////////////////////
     ////////////////////////////////////////////////////////////////////
     // Add the performance monitoring system.
     // Add the performance monitoring system.
diff --git a/src/Main/globals.cxx b/src/Main/globals.cxx
diff --git a/src/Main/globals.cxx b/src/Main/globals.cxx
index d41e00d..c6120f3 100644
index d41e00d..c8805b6 100644
--- a/src/Main/globals.cxx
--- a/src/Main/globals.cxx
+++ b/src/Main/globals.cxx
+++ b/src/Main/globals.cxx
@@ -504,6 +504,7 @@ FGGlobals::add_subsystem (const char * name,
@@ -63,6 +63,7 @@
#include "fg_props.hxx"
#include "fg_io.hxx"
+#include "ram_usage.hxx"
class AircraftResourceProvider : public simgear::ResourceProvider
{
@@ -503,7 +504,12 @@ FGGlobals::add_subsystem (const char * name,
                          SGSubsystemMgr::GroupType type,
                           double min_time_sec)
                           double min_time_sec)
  {
  {
+    MemoryUsageStats* stats = (MemoryUsageStats*) subsystem_mgr->get_subsystem("process-stats");
     subsystem_mgr->add(name, subsystem, type, min_time_sec);
     subsystem_mgr->add(name, subsystem, type, min_time_sec);
+    //snapshot()
+    if(stats) {
+ SG_LOG(SG_GENERAL, SG_ALERT, "Process snapshot after adding subsystem:"<< name);
+    stats->snapshot();
+ }
  }
  }
   
   
Line 355: Line 452:
diff --git a/src/Main/ram_usage.cxx b/src/Main/ram_usage.cxx
diff --git a/src/Main/ram_usage.cxx b/src/Main/ram_usage.cxx
new file mode 100644
new file mode 100644
index 0000000..92d397a
index 0000000..a9da94d
--- /dev/null
--- /dev/null
+++ b/src/Main/ram_usage.cxx
+++ b/src/Main/ram_usage.cxx
@@ -0,0 +1,27 @@
@@ -0,0 +1,17 @@
+#include "ram_usage_linux.hxx"
+#include "ram_usage_linux.hxx"
+
+
+MemoryUsageStats::MemoryUsageStats() {
+MemoryUsageStats::MemoryUsageStats() {
+ _mem = new LinuxMemoryInterface(); //FIXME: should be implemented for Win/Mac & Linux (use SIGAR)
+ _ram = new LinuxMemoryInterface(); //FIXME: should be implemented for Win/Mac & Linux (use SIGAR)
+}
+}
+
+
+MemoryUsageStats::~MemoryUsageStats() {
+MemoryUsageStats::~MemoryUsageStats() {
+ delete _mem;
+ delete _ram;
+}
+}
+
+
+void
+void
+MemoryUsageStats::update(double dt) {
+MemoryUsageStats::update(double dt) {
+   _mem->update(); // will update ram/swap utilization
+update();
+  _mem->updateVRAMStats(); // will update vram utilization
+#if 0
+  int vram = _mem->getVRAMUsageInKB(); // vram tracking stuff
+  int swap = _mem->getSwapSize();
+  int total = _mem->getTotalSize();
+  SG_LOG(SG_GENERAL, SG_DEBUG, "Updating Memory Stats:" << total << " kb");
+  fgSetInt("/memory-usage/swap-usage-kb",  swap );
+  fgSetInt("/memory-usage/total-usage-kb", total );
+  fgSetInt("/memory-usage/vram-available-kb", vram );
+#endif
+}
+}
+
+
Line 388: Line 475:
diff --git a/src/Main/ram_usage.hxx b/src/Main/ram_usage.hxx
diff --git a/src/Main/ram_usage.hxx b/src/Main/ram_usage.hxx
new file mode 100644
new file mode 100644
index 0000000..a1540c1
index 0000000..58abdf5
--- /dev/null
--- /dev/null
+++ b/src/Main/ram_usage.hxx
+++ b/src/Main/ram_usage.hxx
@@ -0,0 +1,175 @@
@@ -0,0 +1,186 @@
+#ifndef __RAM_USAGE
+#ifndef __RAM_USAGE
+#define __RAM_USAGE
+#define __RAM_USAGE
Line 408: Line 495:
+
+
+#include <simgear/timing/timestamp.hxx>
+#include <simgear/timing/timestamp.hxx>
+
+// http://wiki.flightgear.org/Howto:Create_new_subsystems
+#include <simgear/structure/subsystem_mgr.hxx>
+#include <simgear/structure/subsystem_mgr.hxx>
+
+
Line 417: Line 506:
+
+
+using std::map;
+using std::map;
+
+
+// https://github.com/OpenGLInsights/OpenGLInsightsCode/blob/master/Chapter%2038%20Monitoring%20Graphics%20Memory%20Usage/Ch38AMD/Ch38AMD/Ch38AMDDlg.cpp
+#ifndef GL_VBO_FREE_MEMORY_ATI
+
+ #define GL_VBO_FREE_MEMORY_ATI 0x87FB
+ #define GL_TEXTURE_FREE_MEMORY_ATI 0x87FC
+ #define GL_RENDERBUFFER_FREE_MEMORY_ATI 0x87FD
+
+#endif
+
+// http://www.geeks3d.com/20100531/programming-tips-how-to-know-the-graphics-memory-size-and-usage-in-opengl/
+#define GL_GPU_MEM_INFO_TOTAL_AVAILABLE_MEM_NVX 0x9048
+#define GL_GPU_MEM_INFO_CURRENT_AVAILABLE_MEM_NVX 0x9049
+
+
+    // this is the base class, with the only method being a virtual method  
+    // this is the base class, with the only method being a virtual method  
Line 442: Line 517:
+    simgear::PropertyObject<int> total_vram_kb,available_vram_kb, used_vram_kb;
+    simgear::PropertyObject<int> total_vram_kb,available_vram_kb, used_vram_kb;
+    public:
+    public:
+    GPUInfo(): total_mem_kb(-1),  
+    GPUInfo(std::string &glvendor): total_mem_kb(-1),  
+ cur_avail_mem_kb(-1),
+ cur_avail_mem_kb(-1),
+ total_vram_kb("/stats/vram/total-size-kb"),
+ total_vram_kb("/stats/vram/total-size-kb"),
+ available_vram_kb ("/stats/vram/available-kb"),
+ available_vram_kb ("/stats/vram/available-kb"),
+ used_vram_kb ("/stats/vram/used-kb") { }
+ used_vram_kb ("/stats/vram/used-kb") {
+    virtual ~GPUInfo() {
+    SG_LOG(SG_GENERAL, SG_ALERT, "VRAM Tracking: Supported GPU found:"<< glvendor);
+ };
+ }
+    virtual ~GPUInfo() {}
+    virtual void updateVRAMStats() {};
+    virtual void updateVRAMStats() {};
+    };
+    }; //GPUInfo
+  
+  
+    // Actually implement the GPUInfo class for all 3 GPU vendors:
+    // Actually implement the GPUInfo class for all 3 GPU vendors:
+  
+
+    class NVIDIA_GPU: public GPUInfo {
+// http://www.geeks3d.com/20100531/programming-tips-how-to-know-the-graphics-memory-size-and-usage-in-opengl/
+    public:
+#define GL_GPU_MEM_INFO_TOTAL_AVAILABLE_MEM_NVX 0x9048
+    NVIDIA_GPU() {
+#define GL_GPU_MEM_INFO_CURRENT_AVAILABLE_MEM_NVX 0x9049
+
+    struct NVIDIA_GPU: public GPUInfo {
+    NVIDIA_GPU(std::string glvendor) : GPUInfo(glvendor) {
+    // determine total memory and store it (this wont change at runtime, so only do it once)
+    // determine total memory and store it (this wont change at runtime, so only do it once)
+    glGetIntegerv(GL_GPU_MEM_INFO_TOTAL_AVAILABLE_MEM_NVX, &total_mem_kb);
+    glGetIntegerv(GL_GPU_MEM_INFO_TOTAL_AVAILABLE_MEM_NVX, &total_mem_kb);
Line 463: Line 542:
+    }
+    }
+    virtual void updateVRAMStats() {
+    virtual void updateVRAMStats() {
+
+    glGetIntegerv(GL_GPU_MEM_INFO_CURRENT_AVAILABLE_MEM_NVX, &cur_avail_mem_kb);
+    glGetIntegerv(GL_GPU_MEM_INFO_CURRENT_AVAILABLE_MEM_NVX, &cur_avail_mem_kb);
+
+    SG_LOG(SG_GENERAL, SG_DEBUG,"NVIDIA VRAM tracking function says:"<<total_mem_kb<<" (total) available:"<<cur_avail_mem_kb);
+    SG_LOG(SG_GENERAL, SG_DEBUG,"NVIDIA VRAM tracking function says:"<<total_mem_kb<<" (total) available:"<<cur_avail_mem_kb);
+    // update property objects
+    // update property objects
Line 470: Line 549:
+    used_vram_kb = total_vram_kb - available_vram_kb;
+    used_vram_kb = total_vram_kb - available_vram_kb;
+    }
+    }
+    }; //NVIDIA_GPU
+  
+  
+    };
+    struct ATI_GPU: public GPUInfo {
+
+    ATI_GPU(std::string glvendor) : GPUInfo(glvendor) {
+    class ATI_GPU: public GPUInfo {
+    }
+    public:
+    // ATI_GPU()
+    // https://github.com/OpenGLInsights/OpenGLInsightsCode/blob/master/Chapter%2038%20Monitoring%20Graphics%20Memory%20Usage/Ch38AMD/Ch38AMD/Ch38AMDDlg.cpp#L280
+    // https://github.com/OpenGLInsights/OpenGLInsightsCode/blob/master/Chapter%2038%20Monitoring%20Graphics%20Memory%20Usage/Ch38AMD/Ch38AMD/Ch38AMDDlg.cpp#L280
+    virtual void updateVRAMStats() {
+    virtual void updateVRAMStats() {
+// https://github.com/OpenGLInsights/OpenGLInsightsCode/blob/master/Chapter%2038%20Monitoring%20Graphics%20Memory%20Usage/Ch38AMD/Ch38AMD/Ch38AMDDlg.cpp
+#ifndef GL_VBO_FREE_MEMORY_ATI
+ #define GL_VBO_FREE_MEMORY_ATI 0x87FB
+ #define GL_TEXTURE_FREE_MEMORY_ATI 0x87FC
+ #define GL_RENDERBUFFER_FREE_MEMORY_ATI 0x87FD
+#endif
+
+    SG_LOG(SG_GENERAL, SG_ALERT,"Sorry:ATI VRAM tracking function not yet implemented (nvidia only)!");
+    SG_LOG(SG_GENERAL, SG_ALERT,"Sorry:ATI VRAM tracking function not yet implemented (nvidia only)!");
+    used_vram_kb = total_vram_kb = available_vram_kb = -1;
+    used_vram_kb = total_vram_kb = available_vram_kb = -1;
+    }
+    }
+    };//ATI_GPU
+  
+  
+    };
+    struct INTEL_GPU : public GPUInfo {
+
+    INTEL_GPU(std::string glvendor) : GPUInfo(glvendor) {
+    class INTEL_GPU : public GPUInfo {
+}
+   public:
+    virtual void updateVRAMStat() {
+    virtual void updateVRAMStat() {
+    SG_LOG(SG_GENERAL, SG_ALERT,"Sorry:Intel VRAM tracking function not yet implemented (nvidia only)!");
+    SG_LOG(SG_GENERAL, SG_ALERT,"Sorry:Intel VRAM tracking function not yet implemented (nvidia only)!");
Line 491: Line 576:
+    }
+    }
+  
+  
+    };
+    }; // INTEL_GPU
+
+    struct UNKNOWN_GPU: public GPUInfo {
+    UNKNOWN_GPU(std::string glvendor) : GPUInfo(glvendor) {
+    }
+    virtual void updateVRAMStat() {
+    SG_LOG(SG_GENERAL, SG_DEBUG,"Sorry:VRAM tracking function not yet implemented for your GPU (nvidia only)!");
+    used_vram_kb = total_vram_kb = available_vram_kb = -1;
+    }
+   
+    }; // UNKNOWN_GPU
+
+
+// Linux: /proc/pid/smaps
+// Linux: /proc/pid/smaps
Line 515: Line 610:
+    std::size_t found = glvendor.find("NVIDIA");
+    std::size_t found = glvendor.find("NVIDIA");
+      if (found!=std::string::npos) {
+      if (found!=std::string::npos) {
+      _gpu = new NVIDIA_GPU;
+      _gpu = new NVIDIA_GPU(glvendor);
+    }
+    }
+    else if (glvendor.find("INTEL") != std::string::npos) {
+    else if (glvendor.find("INTEL") != std::string::npos) {
+    _gpu = new INTEL_GPU;
+    _gpu = new INTEL_GPU(glvendor);
+ }
+ }
+    else if (glvendor.find("ATI") != std::string::npos) {
+    else if (glvendor.find("ATI") != std::string::npos) {
+    _gpu = new ATI_GPU;
+    _gpu = new ATI_GPU(glvendor);
+ }
+ }
+    else {
+    else {
+   SG_LOG(SG_GENERAL, SG_ALERT, "VRAM Tracking: Unsupported GPU vendor:" << glvendor);
+     _gpu = new UNKNOWN_GPU(glvendor);
+    }
+    }
+
+  if(_gpu)
+      SG_LOG(SG_GENERAL, SG_ALERT, "VRAM Tracking: Supported GPU found:"<< glvendor);
+}
+}
+ typedef map<const char*, double> RamMap;
+ typedef map<const char*, double> RamMap;
+//protected:
+ virtual void update() = 0;
+ virtual void update() = 0;
+
+
Line 539: Line 630:
+}
+}
+
+
+ double getTotalSize() const {return _total_size;}
+ //virtual void  setTotalSize(double t) {_total_size=t;}
+
+ double getSwapSize() const {return _swap_size;}
+ //virtual void  setSwapSize(double s) {_swap_size=s;}
+protected:
+protected:
+ RamMap _size;  
+ RamMap _size;  
+ std::string _path;
+ std::string _path;
+ std::stringstream _pid;
+ std::stringstream _pid;
+ GPUInfo* _gpu;
+ GPUInfo* _gpu; // wraps VRAM utilization gathering
+
+
+ simgear::PropertyObject<int> _total_size;
+public:
+ simgear::PropertyObject<int> _swap_size;
+ simgear::PropertyObject<int> _total_size; // memory used by process
+ simgear::PropertyObject<int> _swap_size; // swap used by process
+};
+};
+
+
Line 560: Line 647:
+ ~MemoryUsageStats();
+ ~MemoryUsageStats();
+  virtual void update(double);
+  virtual void update(double);
+  void snapshot() {
+  update();
+  simgear::PropertyObject<int> used_vram_kb ("/stats/vram/used-kb");
+  SG_LOG(SG_GENERAL, SG_ALERT, "Process size: " <<_ram->_total_size << "kb" << std::endl);
+  // SG_LOG(SG_GENERAL, SG_ALERT, "VRAM utilization: " << used_vram_kb << " kb" << std::endl);
+  }
+
+protected:
+protected:
+private:
+private:
+  MemoryInterface* _mem;
+  MemoryInterface* _ram;
+  void update() {
+  _ram->update(); // will update ram/swap utilization by reading /proc/pid/smaps
+  _ram->updateVRAMStats(); // will update vram utilization by using NVIDIA/AMD APIs
+  }
+};
+};
+
+
Line 651: Line 749:
+
+
+#endif
+#endif
</syntaxhighlight>
</syntaxhighlight>


[[Category:Core development projects]]
[[Category:Core development projects]]

Navigation menu