Performance Hints

Precompiling Scripts

Script loading could be a bit faster if the scripts are precompiled, because compilation overhead is eliminated.

% cd /usr/local/pnuts/modules
% pnutsc -o pnuts-modules-C.jar pnuts-modules.jar
Caveats:

String concatenation

String concatenation by + operator is relatively slow.

a = ""
for (i : 1..10000){
  a += "."
}

This could be rewritten as follows procedure.

First, define a function that prints all strings that you want to concatinate. Then call textGrab() of the pnuts.text module, passing the function just defined. This returns a function that returns the concatinated string.

function f1(){
  for (i : 1..10000){
    print(".")
  }
}

f2 = textGrab(f1)

f2()

Loop

The following loop expression with for statement is relatively slow, because of the overhead of operations on the counter variable.

for(i = 0; i < 1000000; i++){
}

The new expression, for (i:start..end), is faster than the above one.

e.g.
for (i : 0..999999){

}

Accessing Java Beans Properties

Method call such as getXXXX()/setXXXX() can be replaced by XXXX property access so that it gets faster.

now = Date()
longValue = now.time

Generator-style and Callback-style

When there is a heavy weight loop, consider writing in generator-style or callback style.

For example, the code that reads lines sequencially in Pnuts could be rewritten in generator-style, using readLines() function, so that it can eliminate the overhead of method calls.

Loop in Pnuts (slower) Generator-Style (faster) Callback-Style (even faster)
while ((line = reader.readLine()) != null){
    println(line)
}
for (line : readLines(reader)){
   println(line)
}
readLines(reader, println)
m = map()
m.a = 1
m.b = 2
m.c = 3

for (pair : m.entrySet()){
   println(pair.key, "=", pair.value)
}
n/a
m = map()
m.a = 1
m.b = 2
m.c = 3

mapFunction(function (k, v) println(k, "=", v), m)

Choose an appropriate Implementation

pnuts.lang.Implementation class defines an interface of script interpreter's implementation. The following classes are implementation classes of the interface provided in the Pnuts distribution.

pnuts.lang.PnutsImpl
AST interpreter
pnuts.compiler.CompilerPnutsImpl
On-the-fly Compiler
pnuts.ext.CachedPnutsImpl
Mixed mode, which caches compiled (or parsed) scripts and reuse them

On-the-fly compiler usually runs faster than AST interpreter. It is appropriate for interactive use, since the compilation overhead does not matter.

If Pnuts is embedded in an application as a scripting engine and same scripts are executed over and over, mixed mode is the right choice. Since on-the-fly compilation takes a few milliseconds to a few hundreds milliseconds depending on the size of scripts, caching the compiled code would improve the performance.

If the application uses a limited set of scripts, the combination of AST interpreter and precompiled scripts is efficient because there is no compilation overhead and the bytecode compiler package in Pnuts can be removed if needed.

When a method call or an instance creation is a bottle neck:

You might consider to use makeProxy() function.

Implement a function or a loadable class in Java

If you need to eliminate the overhead of script execution caused by reflection API, method search, and so on, there is no reason to avoid implementing a function or a loadable class in Java. See "How to define a function in Java" and "Implementing Loadable Class in Java".