Wednesday, April 13, 2011

Lean and Mean Marsyas by Graham Percival

Marsyas can (sometimes with some modifications) be used to write very efficient code that consumes little resources. It has been used in embedded systems and some mutant versions are even running on guitar effect pedals. The following text was provided by Graham Percival and describes how to avoid the startup cost of the MarSystemManager (a factory for creating MarSystems at run-time). This is also important in web application in which the same processing might be initiated every time there is a request and the startup cost needs to be minimized. This initial startup cost is typically not improtant in batch processing applications as it only takes place at the start of processing.

We all know that "premature optimization is the root of all evil"and the old "1. make it work, 2. make it right, 3. make it fast". But sometimes -- very occasionally, but sometimes -- optimization is not premature. Or else you just feel like being naughty. :) On a more serious note, if you are trying to use Marsyas on a system with limited resources such as an embedded system or mobile phone, it may necessary to optimize before deployment. Most Marsyas examples begin with:

MarSystemManager mng;
This initializes one copy of every MarSystem in Marsyas. This "caching" can save resources if you need to create many copies of certain MarSystems, but if you only need a few MarSystems, it means that your program needs to create (and store) a bunch of unnecessary data. Here's a simple example, contrasting the MarSystemManager way to the "lean and mean" way: you can create individual MarSystems as needed, avoiding the MarSystemManager entirely. Note that you need to include the headers you need yourself! The "lean and mean" technique is particularly useful if you want to statically link your application. You can easily contrast the two methods by commenting out the #define.

#define LEAN

#ifndef LEAN
#include "marsyas/MarSystemManager.h"
#include "marsyas/Series.h"
#include "marsyas/SoundFileSource.h"
#include "marsyas/Rms.h"
#include "marsyas/Annotator.h"
#include "marsyas/WekaSink.h"

using namespace Marsyas;

int main() {
#ifndef LEAN
 MarSystemManager mng;
 MarSystem *net =  mng.create("Series", "extract");
 net->addMarSystem(mng.create("SoundFileSource", "src"));
 net->addMarSystem(mng.create("Rms", "rms"));
 net->addMarSystem(mng.create("Annotator", "annotate"));
 net->addMarSystem(mng.create("WekaSink", "dest"));
 MarSystem *net =   new Series("extract");
 net->addMarSystem( new SoundFileSource("src"));
 net->addMarSystem( new Rms("rms"));
 net->addMarSystem( new Annotator("annotate"));
 net->addMarSystem( new WekaSink("dest"));

// update controls and run the process loop