A technical support community for Apple Logic Pro users.

 
User avatar
Dewdman42
Topic Author
Posts: 3304
Joined: Tue Sep 09, 2014 3:01 pm
Location: Salt Lake City, UT

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

Fri Sep 06, 2019 9:43 am

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 GuiParameters = {
    data: [],
    set: function(id, val) {
        if(typeof id != "string") id = PluginParameters[id].name;
        this.data[id] = val;
    },
    get: 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) {
    GuiParameters.set(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)[/size]

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

After that you can make calls to GuiParameters.get() 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( GuiParameters.get(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 GuiParameter() workaround to avoid this problem.
Last edited by Dewdman42 on Sun Mar 14, 2021 8:29 pm, edited 17 times in total.
OSX 10.15 (Catalina) on OpenCore - Logic Pro 10.6.1, VePro7, Mainstage3
5,1 MacPro 3.46ghz x 12 96gb ram
 
User avatar
Dewdman42
Topic Author
Posts: 3304
Joined: Tue Sep 09, 2014 3:01 pm
Location: Salt Lake City, UT

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

Tue Sep 10, 2019 6:56 pm

Updated the code snippet a little bit today so if you were trying to use this in the past few days, use the new code snippet as of today.
OSX 10.15 (Catalina) on OpenCore - Logic Pro 10.6.1, VePro7, Mainstage3
5,1 MacPro 3.46ghz x 12 96gb ram
 
User avatar
Dewdman42
Topic Author
Posts: 3304
Joined: Tue Sep 09, 2014 3:01 pm
Location: Salt Lake City, UT

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

Sun Mar 14, 2021 8:23 pm

bug found by user benbravo related to using field names instead of field numbers. Bug fix has been posted in first post.
OSX 10.15 (Catalina) on OpenCore - Logic Pro 10.6.1, VePro7, Mainstage3
5,1 MacPro 3.46ghz x 12 96gb ram
 
User avatar
Atlas007
Posts: 9782
Joined: Mon Dec 14, 2009 11:58 pm
Location: Montreal

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

Mon Mar 15, 2021 5:36 pm

Thanx man!
LogicPro 10.6.3, MainStage3.5.3
MBPro 17", Core2Duo, 8G, OSX 10.12.6
MacPro, Xeon 6Cores, 64GB, OSX 10.15.7
ULN8, MOTU MIDI TP-AV, C4, MCU Pro, KorgNano, Novation SLMkII
AAS, NI, Celemony, Spectrasonics, Korg, Arturia, etc...
PC, iPad3(V-Control & LogicRemote), AtariST(Notator SL), Several vintage gear