Howto:Disable Nasal entirely

From FlightGear wiki
Revision as of 15:52, 23 February 2016 by Hooray (talk | contribs)
Jump to navigation Jump to search
This article is a stub. You can help the wiki by expanding it.
disable Nasal scripting
Started in 03/2014
Description provide an optional FlightGear startup mode to disable Nasal scripting entirely for regression testing purpososes
Contributor(s) Hooray
Status unknown

Motivation

Nasal, and particularly its garbage collector (GC), is known for having a certain impact on the frame rate, and frame spacing - however, there are performance issues other than Nasal code - so far, it's been impossible to easily disable Nasal entirely - the following patch makes it possible to disable Nasal completely, so that it can be eliminated from the equation altogether. This startup mode will obviously only be of interest to developers and power-users, i.e. those interested in doing regression testing, and understanding FlightGear issues (resource leaks, performance issues etc).

Objective

disable Nasal scripting

Background

  • Nasal performance
  • garbage collection overhead
  • impact on frame rate and frame spacing
Cquote1.png I should still have an old topic branch that disabled FGNasalSys entirely - i.e. the fg_init.cxx, but also the roughly ~10 places where a handle (pointer) to the FGNasalSys instance in the SGSubsysmMgr is acquired to run some Nasal code on demand (think GUI, joystick, keyboard, AI/scenery stuff).

In and of itself, that will obviously not be particularly useful, because fgfs is rather "crippled" with so much of its (current) UI/aircraft functionality tied to Nasal code all over the place, but it may still be interesting for the FGPythonSys effort, because it provides a good baseline for fgfs performance without _any_ Nasal code running at all, including obviously GC issues - even if only to illustrate (and prove) that FlightGear is still suffering from resource leaks and race conditions that have nothing to do with Nasal.

In other words, this is something where FGPythonSys and FGNasalSys could benefit eachother in the near term, while providing benefits for FG in the long term.
Cquote2.png
Cquote1.png that could be quite useful for experimentation purposes, unit testing, and maybe coming up with a FGScriptingSys base class.
Cquote2.png

Status

updated/rebased patch

News / Updates

Changelog

Gallery

Roadmap

Template:Roadmap

Related

Patch

Note  Add message
diff --git a/src/AIModel/AIManager.cxx b/src/AIModel/AIManager.cxx
index 4faf23e..e09db60 100644
--- a/src/AIModel/AIManager.cxx
+++ b/src/AIModel/AIManager.cxx
@@ -72,6 +72,10 @@ public:
         std::string loadScript = nasalScripts->getStringValue("load");
         if (!loadScript.empty()) {
             FGNasalSys* nasalSys = (FGNasalSys*) globals->get_subsystem("nasal");
+	    if(!nasalSys) { 
+		NASAL_DISABLED("AI scenarios");
+		return;
+	    }
             std::string moduleName = "scenario_" + _internalName;
             nasalSys->createModule(moduleName.c_str(), moduleName.c_str(),
                                    loadScript.c_str(), loadScript.size(),
@@ -86,8 +90,10 @@ public:
         }
         
         FGNasalSys* nasalSys = (FGNasalSys*) globals->get_subsystem("nasal");
-        if (!nasalSys)
-            return;
+        if(!nasalSys) { 
+		NASAL_DISABLED("AI scenarios");
+		return;
+	    }
         
         std::string moduleName = "scenario_" + _internalName;
         if (!_unloadScript.empty()) {
diff --git a/src/GUI/CanvasWidget.cxx b/src/GUI/CanvasWidget.cxx
index f68fe22..52ed2f4 100644
--- a/src/GUI/CanvasWidget.cxx
+++ b/src/GUI/CanvasWidget.cxx
@@ -72,10 +72,13 @@ CanvasWidget::CanvasWidget( int x, int y,
     return;
 
   FGNasalSys *nas = dynamic_cast<FGNasalSys*>(globals->get_subsystem("nasal"));
-  if( !nas )
+  if( !nas ) {
     SG_LOG( SG_GENERAL,
             SG_ALERT,
             "CanvasWidget: Failed to get nasal subsystem!" );
+  NASAL_DISABLED("PUI CanvasWidget");
+  return;
+  }
 
   const std::string file = std::string("__canvas:")
                          + cprops->getStringValue("name");
diff --git a/src/GUI/FGPUIDialog.cxx b/src/GUI/FGPUIDialog.cxx
index 30cbef7..f66f40e 100644
--- a/src/GUI/FGPUIDialog.cxx
+++ b/src/GUI/FGPUIDialog.cxx
@@ -672,7 +672,9 @@ FGPUIDialog::FGPUIDialog (SGPropertyNode *props) :
             FGNasalSys *nas = (FGNasalSys *)globals->get_subsystem("nasal");
             if (nas)
                 nas->createModule(_module.c_str(), _module.c_str(), s, strlen(s), props);
+	    else NASAL_DISABLED("Nasal embedded in PUI dialogs");	
         }
+		
     }
     display(props);
 }
@@ -1056,7 +1058,11 @@ FGPUIDialog::makeObject (SGPropertyNode *props, int parentWidth, int parentHeigh
           }
         } else {
           FGNasalSys* nasal = (FGNasalSys*) globals->get_subsystem("nasal");
+	  if(nasal) 	  
           obj->setBuffer(nasal->log());
+	  else {
+	  NASAL_DISABLED("PUI");
+	  }
         }
 
         setupObject(obj, props);
diff --git a/src/GUI/FileDialog.cxx b/src/GUI/FileDialog.cxx
index 2047898..d71d910 100644
--- a/src/GUI/FileDialog.cxx
+++ b/src/GUI/FileDialog.cxx
@@ -100,6 +100,10 @@ public:
         object(obj)
     {
         FGNasalSys* sys = static_cast<FGNasalSys*>(globals->get_subsystem("nasal"));
+        if(!sys) {
+	NASAL_DISABLED("FileDialog");
+	 return;
+	}
         _gcKeys[0] = sys->gcSave(f);
         _gcKeys[1] = sys->gcSave(obj);
     }
@@ -107,7 +111,10 @@ public:
     virtual void onFileDialogDone(FGFileDialog* instance, const SGPath& aPath)
     {
         FGNasalSys* sys = static_cast<FGNasalSys*>(globals->get_subsystem("nasal"));
-        
+        if(!sys) {
+	NASAL_DISABLED("FileDialog (done)");
+	return;
+	} 
         naContext ctx = naNewContext();
         naRef args[1];
         args[0] = nasal::to_nasal(ctx, aPath);
@@ -119,6 +126,10 @@ public:
     ~NasalCallback()
     {
         FGNasalSys* sys = static_cast<FGNasalSys*>(globals->get_subsystem("nasal"));
+	if(!sys) {
+	NASAL_DISABLED("FileDialog");
+	return;
+	}
         sys->gcRelease(_gcKeys[0]);
         sys->gcRelease(_gcKeys[1]);
     }
diff --git a/src/Input/FGEventInput.cxx b/src/Input/FGEventInput.cxx
index 29bdc6e..7bbab09 100644
--- a/src/Input/FGEventInput.cxx
+++ b/src/Input/FGEventInput.cxx
@@ -236,6 +236,7 @@ FGInputDevice::~FGInputDevice()
     }
     nas->deleteModule(nasalModule.c_str());
   }
+  else NASAL_DISABLED("FGInputDevice");
 } 
 
 void FGInputDevice::Configure( SGPropertyNode_ptr aDeviceNode )
@@ -264,7 +265,7 @@ void FGInputDevice::Configure( SGPropertyNode_ptr aDeviceNode )
       FGNasalSys *nas = (FGNasalSys *)globals->get_subsystem("nasal");
       if (nas)
         nas->createModule(nasalModule.c_str(), nasalModule.c_str(), s.c_str(), s.length(), deviceNode );
-    }
+    } else NASAL_DISABLED("FGInputDevice::Configure");
   }
 
 }
diff --git a/src/Input/FGJoystickInput.cxx b/src/Input/FGJoystickInput.cxx
index 069e9d8..d6d3fd8 100644
--- a/src/Input/FGJoystickInput.cxx
+++ b/src/Input/FGJoystickInput.cxx
@@ -208,14 +208,16 @@ void FGJoystickInput::postinit()
     std::ostringstream str;
     str << "__js" << i;
     std::string module = str.str();
+    unsigned int j;
+    if (nasalsys) {
     nasalsys->createModule(module.c_str(), module.c_str(), "", 0);
 
     PropertyList nasal = js_node->getChildren("nasal");
-    unsigned int j;
     for (j = 0; j < nasal.size(); j++) {
       nasal[j]->setStringValue("module", module.c_str());
       nasalsys->handleCommand(nasal[j]);
     }
+    } else NASAL_DISABLED("Joystick bindings");
 
     //
     // Initialize the axes.
diff --git a/src/Input/FGKeyboardInput.cxx b/src/Input/FGKeyboardInput.cxx
index 8ff3d0a..004547e 100644
--- a/src/Input/FGKeyboardInput.cxx
+++ b/src/Input/FGKeyboardInput.cxx
@@ -109,11 +109,13 @@ void FGKeyboardInput::postinit()
   }
 
   FGNasalSys *nasalsys = (FGNasalSys *)globals->get_subsystem("nasal");
+  if(nasalsys) {
   PropertyList nasal = key_nodes->getChildren("nasal");
   for (unsigned int j = 0; j < nasal.size(); j++) {
     nasal[j]->setStringValue("module", module.c_str());
     nasalsys->handleCommand(nasal[j]);
   }
+} else NASAL_DISABLED("Keyboard bindings");
 
   PropertyList keys = key_nodes->getChildren("key");
   for (unsigned int i = 0; i < keys.size(); i++) {
diff --git a/src/Main/fg_commands.cxx b/src/Main/fg_commands.cxx
index 1e93a0b..e07d4b9 100644
--- a/src/Main/fg_commands.cxx
+++ b/src/Main/fg_commands.cxx
@@ -185,7 +185,13 @@ do_null (const SGPropertyNode * arg)
 static bool
 do_nasal (const SGPropertyNode * arg)
 {
-    return ((FGNasalSys*)globals->get_subsystem("nasal"))->handleCommand(arg);
+    FGNasalSys* nasalSys = (FGNasalSys*) globals->get_subsystem("nasal");
+    if(!nasalSys) {
+	NASAL_DISABLED("fgcomand nasal (bindings)");
+	return false;
+    }
+    return nasalSys->handleCommand(arg);
+    
 }
 
 /**
diff --git a/src/Main/fg_init.cxx b/src/Main/fg_init.cxx
index 61d3425..d8bd11a 100644
--- a/src/Main/fg_init.cxx
+++ b/src/Main/fg_init.cxx
@@ -904,11 +904,12 @@ void fgPostInitSubsystems()
     // Initialize the Nasal interpreter.
     // Do this last, so that the loaded scripts see initialized state
     ////////////////////////////////////////////////////////////////////////
+if(!fgGetBool("/sim/startup/disable-nasal",false)) {
     FGNasalSys* nasal = new FGNasalSys();
     globals->add_subsystem("nasal", nasal, SGSubsystemMgr::INIT);
     nasal->init();
     SG_LOG(SG_GENERAL, SG_INFO, "Nasal init took:" << st.elapsedMSec());
-
+}   else NASAL_DISABLED("Initialization");
     // initialize methods that depend on other subsystems.
     st.stamp();
     globals->get_subsystem_mgr()->postinit();
diff --git a/src/Network/ATC-Main.cxx b/src/Network/ATC-Main.cxx
index 6c0da9b..00cd91a 100644
--- a/src/Network/ATC-Main.cxx
+++ b/src/Network/ATC-Main.cxx
@@ -223,10 +223,12 @@ bool FGATCMain::process() {
     // directly provide.
 
     FGNasalSys *n = (FGNasalSys*)globals->get_subsystem("nasal");
+    if(n) {
     bool result = n->parseAndRun( "atcsim.update()" );
     if ( !result ) {
         SG_LOG( SG_NETWORK, SG_ALERT, "Nasal: atcsim.update() failed!" );
     }
+    } else NASAL_DISABLED("ATC-Main");
 
     // process the ATC outputs
     if ( output0 != NULL && board0_locked ) {
diff --git a/src/Network/HTTPClient.cxx b/src/Network/HTTPClient.cxx
index e6d2b29..48376ab 100644
--- a/src/Network/HTTPClient.cxx
+++ b/src/Network/HTTPClient.cxx
@@ -327,6 +327,10 @@ void FGHTTPClient::postinit()
   pkg::Root* packageRoot = globals->packageRoot();
   if (packageRoot) {
     FGNasalSys* nasalSys = (FGNasalSys*) globals->get_subsystem("nasal");
+    if(!nasalSys) {
+	NASAL_DISABLED("package manager");
+	return;
+	}
     nasal::Hash nasalGlobals = nasalSys->getGlobals();
     nasal::Hash nasalPkg = nasalGlobals.createHash("pkg"); // module
     nasalPkg.set("root", packageRoot);
diff --git a/src/Scripting/NasalSys.hxx b/src/Scripting/NasalSys.hxx
index 096a591..af01ff2 100644
--- a/src/Scripting/NasalSys.hxx
+++ b/src/Scripting/NasalSys.hxx
@@ -30,11 +30,14 @@ namespace simgear { class BufferedLogCallback; }
 
 SGPropertyNode* ghostToPropNode(naRef ref);
 
+#define NASAL_DISABLED(feature) SG_LOG(SG_NASAL, SG_ALERT, "Nasal support disabled:" << feature)
+
 class FGNasalSys : public SGSubsystem
 {
 public:
     FGNasalSys();
     virtual ~FGNasalSys();
+
     virtual void init();
     virtual void shutdown();