20,741
edits
mNo edit summary |
m (→Proof of concept (patch): removed leading whitespaces (which broke syntaxhighlighting)) |
||
Line 226: | Line 226: | ||
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 -urN a/src/Main/CMakeLists.txt b/src/Main/CMakeLists.txt | |||
--- a/src/Main/CMakeLists.txt 2015-08-20 23:03:15.070835000 +0300 | |||
+++ b/src/Main/CMakeLists.txt 2015-08-20 23:26:58.706798388 +0300 | |||
@@ -17,12 +17,17 @@ | |||
main.cxx | |||
options.cxx | |||
util.cxx | |||
+ ram_usage.cxx | |||
positioninit.cxx | |||
subsystemFactory.cxx | |||
screensaver_control.cxx | |||
${RESOURCE_FILE} | |||
) | |||
+IF(${CMAKE_SYSTEM_NAME} MATCHES "Linux") | |||
+ list(APPEND SOURCES ram_usage_linux.cxx) | |||
+ENDIF(${CMAKE_SYSTEM_NAME} MATCHES "Linux") | |||
+ | |||
set(HEADERS | |||
fg_commands.hxx | |||
fg_init.hxx | |||
@@ -35,12 +40,19 @@ | |||
main.hxx | |||
options.hxx | |||
util.hxx | |||
+ ram_usage.hxx | |||
positioninit.hxx | |||
subsystemFactory.hxx | |||
AircraftDirVisitorBase.hxx | |||
screensaver_control.hxx | |||
) | |||
+IF(${CMAKE_SYSTEM_NAME} MATCHES "Linux") | |||
+ list(APPEND HEADERS ram_usage_linux.hxx) | |||
+ENDIF(${CMAKE_SYSTEM_NAME} MATCHES "Linux") | |||
+ | |||
+ | |||
+ | |||
get_property(FG_SOURCES GLOBAL PROPERTY FG_SOURCES) | |||
get_property(FG_HEADERS GLOBAL PROPERTY FG_HEADERS) | |||
diff -urN a/src/Main/fg_init.cxx b/src/Main/fg_init.cxx | |||
--- a/src/Main/fg_init.cxx 2015-08-20 23:22:52.166804000 +0300 | |||
+++ b/src/Main/fg_init.cxx 2015-08-20 23:29:15.074794813 +0300 | |||
@@ -141,6 +141,7 @@ | |||
#include "globals.hxx" | |||
#include "logger.hxx" | |||
#include "main.hxx" | |||
+#include "ram_usage.hxx" | |||
#include "positioninit.hxx" | |||
#include "util.hxx" | |||
#include "AircraftDirVisitorBase.hxx" | |||
@@ -715,6 +716,10 @@ | |||
//////////////////////////////////////////////////////////////////// | |||
globals->add_subsystem("properties", new FGProperties); | |||
+ //////////////////////////////////////////////////////////////////// | |||
+ // Add the ram usage statistics system | |||
+ //////////////////////////////////////////////////////////////////// | |||
+ globals->add_subsystem("memory-stats", new MemoryUsageStats, SGSubsystemMgr::INIT, 5.00); | |||
//////////////////////////////////////////////////////////////////// | |||
// Add the performance monitoring system. | |||
diff -urN a/src/Main/ram_usage.cxx b/src/Main/ram_usage.cxx | |||
--- a/src/Main/ram_usage.cxx 1970-01-01 03:00:00.000000000 +0300 | |||
+++ b/src/Main/ram_usage.cxx 2015-08-20 23:29:53.950793794 +0300 | |||
@@ -0,0 +1,22 @@ | |||
+#include "ram_usage_linux.hxx" | |||
+ | |||
+MemoryUsageStats::MemoryUsageStats() { | |||
+ _mem = new LinuxMemoryInterface(); //FIXME: should be implemented for Win/Mac & Linux | |||
+} | |||
+ | |||
+MemoryUsageStats::~MemoryUsageStats() { | |||
+ delete _mem; | |||
+} | |||
+ | |||
+void | |||
+MemoryUsageStats::update(double dt) { | |||
+ _mem->update(); | |||
+ double swap = _mem->getSwapSize(); | |||
+ double 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 ); | |||
+} | |||
+ | |||
+ | |||
+ | |||
diff -urN a/src/Main/ram_usage.hxx b/src/Main/ram_usage.hxx | |||
--- a/src/Main/ram_usage.hxx 1970-01-01 03:00:00.000000000 +0300 | |||
+++ b/src/Main/ram_usage.hxx 2015-08-20 23:29:53.950793794 +0300 | |||
@@ -0,0 +1,51 @@ | |||
+#ifndef __RAM_USAGE | |||
+#define __RAM_USAGE | |||
+ | |||
+#include <simgear/timing/timestamp.hxx> | |||
+#include <simgear/structure/subsystem_mgr.hxx> | |||
+ | |||
+#include <Main/globals.hxx> | |||
+#include <Main/fg_props.hxx> | |||
+ | |||
+#include <string> | |||
+#include <map> | |||
+ | |||
+using std::map; | |||
+ | |||
+// Linux: /proc/pid/smaps | |||
+// Windows: http://msdn.microsoft.com/en-us/library/windows/desktop/ms682050(v=vs.85).aspx | |||
+ | |||
+class MemoryInterface { | |||
+public: | |||
+ MemoryInterface() {} | |||
+ typedef map<const char*, double> RamMap; | |||
+//protected: | |||
+ virtual void update() = 0; | |||
+ | |||
+ 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: | |||
+ RamMap _size; | |||
+ std::string _path; | |||
+ std::stringstream _pid; | |||
+ | |||
+ double _total_size; | |||
+ double _swap_size; | |||
+}; | |||
+ | |||
+class MemoryUsageStats : public SGSubsystem | |||
+{ | |||
+public: | |||
+ MemoryUsageStats(); | |||
+ ~MemoryUsageStats(); | |||
+ virtual void update(double); | |||
+protected: | |||
+private: | |||
+ MemoryInterface* _mem; | |||
+}; | |||
+ | |||
+#endif | |||
+ | |||
diff -urN a/src/Main/ram_usage_linux.cxx b/src/Main/ram_usage_linux.cxx | |||
--- a/src/Main/ram_usage_linux.cxx 1970-01-01 03:00:00.000000000 +0300 | |||
+++ b/src/Main/ram_usage_linux.cxx 2015-08-20 23:29:53.950793794 +0300 | |||
@@ -0,0 +1,49 @@ | |||
+// https://gist.github.com/896026/c346c7c8e4a9ab18577b4e6abfca37e358de83c1 | |||
+ | |||
+#include "ram_usage_linux.hxx" | |||
+ | |||
+#include <cstring> | |||
+#include <string> | |||
+ | |||
+#include "Main/globals.hxx" | |||
+ | |||
+using std::string; | |||
+ | |||
+LinuxMemoryInterface::LinuxMemoryInterface() { | |||
+ _pid << getpid(); | |||
+ _path = "/proc/"+ _pid.str() +"/smaps"; | |||
+} | |||
+ | |||
+void | |||
+LinuxMemoryInterface::OpenProcFile() { | |||
+ file = fopen(_path.c_str(),"r" ); | |||
+ if (!file) { | |||
+ throw("MemoryTracker:Cannot open /proc/pid/smaps"); | |||
+ } | |||
+ SG_LOG(SG_GENERAL, SG_DEBUG, "Opened:"<< _path.c_str() ); | |||
+} | |||
+ | |||
+LinuxMemoryInterface::~LinuxMemoryInterface() { | |||
+ if (file) fclose(file); | |||
+} | |||
+ | |||
+void LinuxMemoryInterface::update() { | |||
+ OpenProcFile(); | |||
+ if (!file) throw("MemoryTracker: ProcFile not open"); | |||
+ | |||
+ _total_size = 0; | |||
+ _swap_size = 0; | |||
+ | |||
+ char line[1024]; | |||
+ while (fgets(line, sizeof line, file)) | |||
+ { | |||
+ char substr[32]; | |||
+ int n; | |||
+ if (sscanf(line, "%31[^:]: %d", substr, &n) == 2) { | |||
+ if (strcmp(substr, "Size") == 0) { _total_size += n; } | |||
+ else if (strcmp(substr, "Swap") == 0) { _swap_size += n; } | |||
+ } | |||
+ } | |||
+ fclose(file); | |||
+} | |||
+ | |||
diff -urN a/src/Main/ram_usage_linux.hxx b/src/Main/ram_usage_linux.hxx | |||
--- a/src/Main/ram_usage_linux.hxx 1970-01-01 03:00:00.000000000 +0300 | |||
+++ b/src/Main/ram_usage_linux.hxx 2015-08-20 23:29:53.950793794 +0300 | |||
@@ -0,0 +1,22 @@ | |||
+#ifndef __RAM_USAGE_LINUX | |||
+#define __RAM_USAGE_LINUX | |||
+ | |||
+ #include <sys/types.h> | |||
+ #include <unistd.h> | |||
+ #include <stdio.h> | |||
+ | |||
+ #include "ram_usage.hxx" | |||
+ | |||
+class LinuxMemoryInterface : public MemoryInterface { | |||
+public: | |||
+ LinuxMemoryInterface(); | |||
+~LinuxMemoryInterface(); | |||
+ virtual void update(); | |||
+private: | |||
+ void OpenProcFile(); | |||
+ const char* filename; | |||
+ FILE *file; | |||
+}; | |||
+ | |||
+ | |||
+#endif | |||
+ | |||
</syntaxhighlight> | </syntaxhighlight> | ||
[[Category:Core development projects]] | [[Category:Core development projects]] |