20,741
edits
m (→Proof of concept (patch): http://sourceforge.net/p/flightgear/mailman/message/34370832/) |
m (→Proof of concept (patch): updates from User:hamzaalloush: http://pastebin.com/h8dGECYv#) |
||
Line 223: | Line 223: | ||
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 - | 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 | |||
--- a/src/Main/CMakeLists.txt | +++ b/src/Main/CMakeLists.txt 2015-08-20 23:26:58.706798388 +0300 | ||
+++ b/src/Main/CMakeLists.txt | @@ -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") | +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 | |||
+IF(${CMAKE_SYSTEM_NAME} MATCHES "Linux") | positioninit.hxx | ||
+ list(APPEND HEADERS ram_usage_linux.hxx) | subsystemFactory.hxx | ||
+ENDIF(${CMAKE_SYSTEM_NAME} MATCHES "Linux") | AircraftDirVisitorBase.hxx | ||
+ | screensaver_control.hxx | ||
+ | ) | ||
+ | |||
+IF(${CMAKE_SYSTEM_NAME} MATCHES "Linux") | |||
+ list(APPEND HEADERS ram_usage_linux.hxx) | |||
+ENDIF(${CMAKE_SYSTEM_NAME} MATCHES "Linux") | |||
diff - | + | ||
+ | |||
--- a/src/Main/fg_init.cxx | + | ||
+++ b/src/Main/fg_init.cxx | 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 | |||
+#include "ram_usage.hxx" | @@ -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 @@ | ||
+ // Add the ram usage statistics system | //////////////////////////////////////////////////////////////////// | ||
+ //////////////////////////////////////////////////////////////////// | globals->add_subsystem("properties", new FGProperties); | ||
+ globals->add_subsystem("memory-stats", new MemoryUsageStats, SGSubsystemMgr::INIT, 5.00); | |||
+ //////////////////////////////////////////////////////////////////// | |||
+ // Add the ram usage statistics system | |||
+ //////////////////////////////////////////////////////////////////// | |||
diff - | + globals->add_subsystem("memory-stats", new MemoryUsageStats, SGSubsystemMgr::INIT, 5.00); | ||
//////////////////////////////////////////////////////////////////// | |||
--- / | // Add the performance monitoring system. | ||
+++ b/src/Main/ram_usage.cxx | 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 | |||
+#include "ram_usage_linux.hxx" | +++ b/src/Main/ram_usage.cxx 2015-08-20 23:29:53.950793794 +0300 | ||
+ | @@ -0,0 +1,22 @@ | ||
+MemoryUsageStats::MemoryUsageStats() { | +#include "ram_usage_linux.hxx" | ||
+ _mem = new LinuxMemoryInterface(); //FIXME: should be implemented for Win/Mac & Linux | + | ||
+} | +MemoryUsageStats::MemoryUsageStats() { | ||
+ | + _mem = new LinuxMemoryInterface(); //FIXME: should be implemented for Win/Mac & Linux | ||
+MemoryUsageStats::~MemoryUsageStats() { | +} | ||
+ delete _mem; | + | ||
+} | +MemoryUsageStats::~MemoryUsageStats() { | ||
+ | + delete _mem; | ||
+void | +} | ||
+MemoryUsageStats::update(double dt) { | + | ||
+ _mem->update(); | +void | ||
+ double swap = _mem->getSwapSize(); | +MemoryUsageStats::update(double dt) { | ||
+ double total = _mem->getTotalSize(); | + _mem->update(); | ||
+ SG_LOG(SG_GENERAL, SG_DEBUG, "Updating Memory Stats:" << total << " kb"); | + double swap = _mem->getSwapSize(); | ||
+ fgSetInt("/memory-usage/swap-usage-kb", swap ); | + double total = _mem->getTotalSize(); | ||
+ fgSetInt("/memory-usage/total-usage-kb", total ); | + 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 - | + | ||
+ | |||
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 | +++ b/src/Main/ram_usage.hxx 2015-08-20 23:29:53.950793794 +0300 | ||
@@ -0,0 +1,51 @@ | |||
+#ifndef __RAM_USAGE | +#ifndef __RAM_USAGE | ||
+#define __RAM_USAGE | +#define __RAM_USAGE | ||
+ | + | ||
+#include <simgear/timing/timestamp.hxx> | +#include <simgear/timing/timestamp.hxx> | ||
+#include <simgear/structure/subsystem_mgr.hxx> | +#include <simgear/structure/subsystem_mgr.hxx> | ||
+ | + | ||
+#include <Main/globals.hxx> | +#include <Main/globals.hxx> | ||
+#include <Main/fg_props.hxx> | +#include <Main/fg_props.hxx> | ||
+ | + | ||
+#include <string> | +#include <string> | ||
+#include <map> | +#include <map> | ||
+ | + | ||
+using std::map; | +using std::map; | ||
+ | + | ||
+// Linux: /proc/pid/smaps | +// Linux: /proc/pid/smaps | ||
+// Windows: http://msdn.microsoft.com/en-us/library/windows/desktop/ms682050(v=vs.85).aspx | +// Windows: http://msdn.microsoft.com/en-us/library/windows/desktop/ms682050(v=vs.85).aspx | ||
+ | + | ||
+class MemoryInterface { | +class MemoryInterface { | ||
+public: | +public: | ||
+ MemoryInterface() {} | + MemoryInterface() {} | ||
+ typedef map<const char*, double> RamMap; | + typedef map<const char*, double> RamMap; | ||
+//protected: | +//protected: | ||
+ virtual void update() = 0; | + virtual void update() = 0; | ||
+ | + | ||
+ double getTotalSize() const {return _total_size;} | + double getTotalSize() const {return _total_size;} | ||
+ //virtual void setTotalSize(double t) {_total_size=t;} | + //virtual void setTotalSize(double t) {_total_size=t;} | ||
+ | + | ||
+ double getSwapSize() const {return _swap_size;} | + double getSwapSize() const {return _swap_size;} | ||
+ //virtual void setSwapSize(double s) {_swap_size=s;} | + //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; | ||
+ | + | ||
+ double _total_size; | + double _total_size; | ||
+ double _swap_size; | + double _swap_size; | ||
+}; | +}; | ||
+ | + | ||
+class MemoryUsageStats : public SGSubsystem | +class MemoryUsageStats : public SGSubsystem | ||
+{ | +{ | ||
+public: | +public: | ||
+ MemoryUsageStats(); | + MemoryUsageStats(); | ||
+ ~MemoryUsageStats(); | + ~MemoryUsageStats(); | ||
+ virtual void update(double); | + virtual void update(double); | ||
+protected: | +protected: | ||
+private: | +private: | ||
+ MemoryInterface* _mem; | + MemoryInterface* _mem; | ||
+}; | +}; | ||
+ | + | ||
+#endif | +#endif | ||
+ | + | ||
diff - | 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 @@ | ||
+++ b/src/Main/ram_usage_linux.cxx | +// https://gist.github.com/896026/c346c7c8e4a9ab18577b4e6abfca37e358de83c1 | ||
@@ -0,0 +1,49 @@ | + | ||
+// https://gist.github.com/896026/c346c7c8e4a9ab18577b4e6abfca37e358de83c1 | +#include "ram_usage_linux.hxx" | ||
+ | + | ||
+#include "ram_usage_linux.hxx" | +#include <cstring> | ||
+ | +#include <string> | ||
+#include <cstring> | + | ||
+#include <string> | +#include "Main/globals.hxx" | ||
+ | + | ||
+#include "Main/globals.hxx" | +using std::string; | ||
+ | + | ||
+using std::string; | +LinuxMemoryInterface::LinuxMemoryInterface() { | ||
+ | + _pid << getpid(); | ||
+LinuxMemoryInterface::LinuxMemoryInterface() { | + _path = "/proc/"+ _pid.str() +"/smaps"; | ||
+ _pid << getpid(); | +} | ||
+ _path = "/proc/"+ _pid.str() +"/smaps"; | + | ||
+} | +void | ||
+ | +LinuxMemoryInterface::OpenProcFile() { | ||
+void | + file = fopen(_path.c_str(),"r" ); | ||
+LinuxMemoryInterface::OpenProcFile() { | + if (!file) { | ||
+ file = fopen(_path.c_str(),"r" ); | + throw("MemoryTracker:Cannot open /proc/pid/smaps"); | ||
+ if (!file) { | + } | ||
+ throw("MemoryTracker:Cannot open /proc/pid/smaps"); | + SG_LOG(SG_GENERAL, SG_DEBUG, "Opened:"<< _path.c_str() ); | ||
+ } | +} | ||
+ SG_LOG(SG_GENERAL, SG_DEBUG, "Opened:"<< _path.c_str() ); | + | ||
+} | +LinuxMemoryInterface::~LinuxMemoryInterface() { | ||
+ | + if (file) fclose(file); | ||
+LinuxMemoryInterface::~LinuxMemoryInterface() { | +} | ||
+ if (file) fclose(file); | + | ||
+} | +void LinuxMemoryInterface::update() { | ||
+ | + OpenProcFile(); | ||
+void LinuxMemoryInterface::update() { | + if (!file) throw("MemoryTracker: ProcFile not open"); | ||
+ OpenProcFile(); | + | ||
+ if (!file) throw("MemoryTracker: ProcFile not open"); | + _total_size = 0; | ||
+ | + _swap_size = 0; | ||
+ _total_size = 0; | + | ||
+ _swap_size = 0; | + char line[1024]; | ||
+ | + while (fgets(line, sizeof line, file)) | ||
+ char line[1024]; | + { | ||
+ while (fgets(line, sizeof line, file)) | + char substr[32]; | ||
+ { | + int n; | ||
+ char substr[32]; | + if (sscanf(line, "%31[^:]: %d", substr, &n) == 2) { | ||
+ int n; | + if (strcmp(substr, "Size") == 0) { _total_size += n; } | ||
+ if (sscanf(line, "%31[^:]: %d", substr, &n) == 2) { | + else if (strcmp(substr, "Swap") == 0) { _swap_size += n; } | ||
+ if (strcmp(substr, "Size") == 0) { _total_size += n; } | + } | ||
+ else if (strcmp(substr, "Swap") == 0) { _swap_size += n; } | + } | ||
+ } | + fclose(file); | ||
+ } | +} | ||
+ 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 | ||
diff - | +++ 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 | ||
+ | |||
@@ -0,0 +1,22 @@ | + #include <sys/types.h> | ||
+#ifndef __RAM_USAGE_LINUX | + #include <unistd.h> | ||
+#define __RAM_USAGE_LINUX | + #include <stdio.h> | ||
+ | + | ||
+ #include <sys/types.h> | + #include "ram_usage.hxx" | ||
+ #include <unistd.h> | + | ||
+ | +class LinuxMemoryInterface : public MemoryInterface { | ||
+ #include "ram_usage.hxx" | +public: | ||
+ | + LinuxMemoryInterface(); | ||
+class LinuxMemoryInterface : public MemoryInterface { | +~LinuxMemoryInterface(); | ||
+public: | + virtual void update(); | ||
+ LinuxMemoryInterface(); | +private: | ||
+~LinuxMemoryInterface(); | + void OpenProcFile(); | ||
+ virtual void update(); | + const char* filename; | ||
+private: | + FILE *file; | ||
+ void OpenProcFile(); | +}; | ||
+ const char* filename; | + | ||
+ FILE *file; | + | ||
+}; | +#endif | ||
+ | + | ||
+ | |||
+#endif | |||
+ | |||
</syntaxhighlight> | </syntaxhighlight> | ||
[[Category:Core development projects]] | [[Category:Core development projects]] |