Does Rhino auto-optimize scripts like how Node.js does?

Viewed 374

I wanted to test different ways to search through a text and their impact on time. To do that I wrote this:

// test case 1: no regex instance & regex.exec
let t1total = 0;
for (let j = 0; j < trialCount; j++){
    let start = performance.now();
    for (let i = 0; i < splitLog.length; i++) {
        /^([A-Z]+)[^\d]+([\d\/\-.:]+\sUTC)/.exec(splitLog[i]);
    }
    let end = performance.now();
    t1total += end - start
}
t1total /= trialCount;

// test case 2: pre-compile + regex.exec
let t2total = 0;
let compileStart = performance.now();
const preRegex = new RegExp(/^([A-Z]+)[^\d]+([\d\/\-.:]+\sUTC)/);
let compileEnd = performance.now();
t2total += compileEnd - compileStart;
for (let j = 0; j < trialCount; j++){
    let start = performance.now();
    for (let i = 0; i < splitLog.length; i++) {
        preRegex.exec(splitLog[i]);
    }
    let end = performance.now();
    t2total += end - start
}
t2total /= trialCount;

I wanted to run this over many trials and take an average to get a more consistent result, but realized that node automatically optimizes such a situation.

Results in ms for 1 trial: Test 1: no regex instance + regex.exec 9.151600003242493 Test 2: pre-compile + regex.exec 4.707100033760071

Results in ms for 1000 trials: Test 1: no regex instance + regex.exec 2.340533686041832 Test 2: pre-compile + regex.exec 2.199146592259407

So node will do this optimization on itself when repeatedly creating the same regex.

Now imagine having a script where exec is called only once on a regex that hasn't been instantiated. Will Rhino repeatedly calling such a script have a similar optimization to node running a loop like test case 1's?

In other words, Does Rhino optimize repeatedly calling a script that instantiates a regex, similar to how nodejs optimizes repeatedly instantiating the same regex?

1 Answers

I ran some tests to try and figure this out and there does seem to be a similar automatic optimization, but it is a noticeable difference between different methods - unlike my results with Node.js.

Trials : 1
Lines: 35629
Regex compile time:  111859500

no instance + exec:  196013300
precompile + exec:   127519700
no instance + match: 116066300
precompile + match:  68303500
~~~~~~~~~~~~~~~~~~~~~~~~~~~
Trials: 1000
Lines: 35629
Regex compile time:  99829400

no instance + exec:  40101506
precompile + exec:   37426255
no instance + match: 45371233
precompile + match:  44917744

The strange thing is that my results really seem to change significantly depending on how many trials are run. Also, re-instantiating scripts seems to interrupt this optimization. Full results can be found here.

I created a "precompiled" regex by compiling a regex in a script then pulling that out into a java object. I would then pass that object as an argument to scripts which needed an already compiled regex to do a search.

Note: Results only time the scripts that run searches and does not include the time to create the regex or scripts themselves.

Related