I'm constructing a framework in Java that will listen for events and then process them in Jython. Different event types will be sent to different scripts.
Since jython takes quite some time to compile the script when PythonInterpreter.exec() is called, I will have to pre-compile the scripts. I'm doing it the following way:
// initialize the script as string (would load it from file in final version)
String script = "print 'foo'";
// get the compiled code object
PyCode compiled = org.python.core.__builtin__.compile( script, "<>", "exec" );
The PyCode compiled object would be pushed to repository and used as events come in
PythonInterpreter pi = new PythonInterpreter();
pi.set( "variable_1", "value_1");
pi.set( "variable_x", "value_x");
pi.exec( compiled );
Now for my conundrum - it might happen that there are multiple events of certain type happening at the same time - thus multiple instances of script running at the same time.
Almost all scripts would probably remain short-lived - up to 100 lines, no loops. Number and frequency is completely random (user generated events) and could be from 0 to about 200 per second per event type.
What would the best way to do it be? I'm looking at a few possibilities:
- use synchronization at trigger event point - this would prevent multiple instances of same script but also events wouldn't be processed as quickly as they should be
- create a pool of same type scripts somehow populated by cloning original PyCode object - the biggest problem would probably be optimizing pool sizes
- dynamically clone the script object from the parent whenever needed and then discard it when exec() finishes - this way the lag is removed from compile but it is still present in clone method
Probably the combination of number 2 and 3 would be the best - creating dynamic pool sizes?
So, any thoughts? ;)
It is a pity that
PyCode
instances aren't immutable (there are a lot of public members on the classes).You can precompile a reusable script using this code:
You can then use the constructor to produce PyCode instances for the script whenever you need one:
I would be the first to admit that this is not a good way of doing things and probably speaks volumes about my inexperience with Jython. However, it is significantly faster than compiling every time. The code works under Jython 2.2.1, but won't compile under Jython 2.5 (nor will yours).
PythonInterpreter is expensive, this code will use only one.