Caching Nasal function calls

From FlightGear wiki
Jump to navigation Jump to search
This article is a stub. You can help the wiki by expanding it.


To cache expensive function calls, you can store their results in a lookup table and avoid repeated calling of the function if the value has already been computed - here's a very simple example, that isn't really heavy - just to illustrate the concept:

# Those subs should be "inline" for speed, but this is more readable
var Ysin = func (s) {
    return math.sin(s*p)*150+y1;  # currently 150 is + and - top value
};

var Ycos = func (s) {
    return math.cos(s*p)*150+y1;
};

Next, introduce a cache class and a memoize class to create new cached functions:

var cache = {};
cache.new = func return { parents:[cache] };

var memoize = { callback:nil };

memoize.new = func(code) {
    return { parents:[memoize], callback:code, cache:cache.new() };
}

memoize._save = func(value) me.cache[value] = me.callback(value);
memoize.lookup = func(value) {
    var found = me.cache[value];
    if (found) {
        print("cached:",found,"\n");
        return found;
    }
    print("not cached:");
    return me._save(value);
}

var p = (2*math.pi)/360; # we don't want to calculate over and over.
var y1 = 151;

var Ycos = memoize.new( func (s) {
    return math.cos(s*p)*150+y1; 
} );
var Ysin = memoize.new( func (s) {
    return math.sin(s*p)*150+y1;
} );

print( id(Ysin.cache) );
print("\n");
print( id(Ycos.cache) );

##
# test:
#
Ysin.lookup(3);
Ycos.lookup(3);
Ysin.lookup(4);
Ysin.lookup(3);

As a further step towards readability, make a function wrapper to remove the ".lookup" syntax:

var Ysinf = func(s) Ysin.lookup(s);
var Xsinf = func(s) Xsin.lookup(s);