Jump to content

TIP: GetParameter is inefficient, here's a work around


Dewdman42

Recommended Posts

GetParameter Workaround

Summary

The GetParameter method in Scripter is a very expensive operation in Scripter. I measured it to be 60 times slower then a simple assignment (see below). This results in some CPU overhead that could effect CPU usage or even cause some dropped midi events when called often inside ProcessMIDI or HandleMIDI callbacks.

Solution

First, here is a simple solution. Copy and paste the following code into your Scripter script:

var EXT = {
   data: [],
   SetParameter: function(id, val) {
       if(typeof id != "string") id = PluginParameters[id].name;
       this.data[id] = val;
   },
   GetParameter: function(id) {
       if(typeof id != "string") id = PluginParameters[id].name;
       if(this.data[id] == undefined) {
           this.data[id] = GetParameter(id);
       }
       return this.data[id];
   }
};
function ParameterChanged(id, val) {
   EXT.SetParameter(id, val);
}
 
 

(Note, if your script is already utilizing the ParameterChanged callback, then add the single line of code to your version of that function)

The above will provide a new object called EXT, which includes both a EXT.GetParameter and a EXT.SetParameter method. use these instead of the normal GetParameter for obtaining the current GUI control values.

After that you can make calls to EXT.GetParameter() to obtain GUI control values, 60 times faster. Like this:

function HandleMIDI(event) {
   // If GUI control 1 set to value of 2, then do this
   if( EXT.GetParameter(1) == 2 ) {
       event.send();
   }
}

Deeper Explanation

I have been noticing that calls to GetParameter() can be rather costly in terms of CPU usage. Scripter is doing a lot of work under the covers with this call in order to obtain the current value of a Scripter GUI control. I set out to measure this, and found that GetParameter() requires as much as 60 times as much time to retrieve a GUI control value as it takes to assign a value from a variable. In other words, the first example below is 60 times slower then the second example:

var value = GetParameter(1);
 
var value = "some value";
 

You can test this yourself. The following script was used to measure this. Copy and paste the following script into Scripter and hit the RunScript button, then hit a key on your midi keyboard 10 times, to run the test, after 10 times it will display an average also:

var PluginParameters = [];

PluginParameters.push({
   name: "fieldOne",
   type: "menu",
   valueStrings: ["one","two","Three"],
   defaultValue: 0
});

PluginParameters.push({
   name: "fieldTwo",
   type: "menu",
   valueStrings: ["one","two","Three"],
   defaultValue: 1
});

PluginParameters.push({
   name: "fieldTwo",
   type: "menu",
   valueStrings: ["one","two","Three"],
   defaultValue: 1
});

var testCount=0;
var results = [];

function HandleMIDI(event) {

   var start = Date.now();
   for(i=0;i<10000;i++) {
       var val = GetParameter(1);
   }
   var end = Date.now();
   var time = end-start;
   
   //Trace("1000 iterations in "+ time +" ms");
   console.log("Time Per Op(GetParameter): "+time/10000+ " ms");

   results[testCount] = {};
   results[testCount].getParam = time/10000;
   
   var start = Date.now();
   for(i=0;i<10000;i++) {
       var val = GuiParameters.get(1);
   }
   var end = Date.now();
   var time = end-start;

    console.log("Time Per Op(assign): "+time/10000+ " ms");
    
    results[testCount].assign = time/10000;
    testCount++;
 
}

function Idle() {
   if(testCount==20) { 
       var gsum = 0;
       var asum = 0;
       for(var i=0;i<testCount;i++) {
            gsum += results[i].getParam;
            asum += results[i].assign;
       }
       
       var gavg = gsum/testCount;
       var aavg = asum/testCount;
       
       console.log("Average GetParameter Op Time = "+gavg+ " ms");
       console.log("Average Assign Op Time = "+aavg+" ms");
       console.log("GetParameter is "+gavg/aavg+" times slower");
   }
   console.flush();
}

var GuiParameters = {
   data: [],
   set: function(id, val) {
       this.data[id] = val;
   },
   get: function(id) {
       if(this.data[id] == undefined) {
           this.data[id] = GetParameter(id);
       }
       return this.data[id];
   }
};
function ParameterChanged(id, val) {
   GuiParameters.set(id, val);
}

var console = {
   maxFlush: 20,
   buffer: [],
   log: function(msg) {
       this.buffer.push(msg);
   },
   flush: function() {
       var i=0;
       while(i<=this.maxFlush && this.buffer.length>0) {
           Trace(this.buffer.shift());
           i++;
       }
   }
};
 
Average GetParameter Op Time = 0.016355 ms
Average Assign Op Time = 0.00026999999999999995 ms
GetParameter is 60.57407407407409 times slower
 

As you can see above, GetParameter() is still able to retrieve GUI control values in considerably less than a millisecond, so if you are only doing this occasionally in your scripts, it won't matter at all. However if you write a script that is perhaps calling GetParameter quite often, then this could begin to impact CPU usage and/or cause event dropping to occur. Use the EXT.GetParameter() workaround to avoid this problem.

  • Like 1
Link to comment
Share on other sites

  • 1 year later...

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...