Groovy test 1: 394ms average
import org.slf4j.LoggerFactory;
scriptExtension.importPreset("cache");
long elapsed_time;
long start_time = System.currentTimeMillis();
long end_time;
float counter = 0.2;
float rate = 3.54409;
privateCache.put('counter', counter);
for (int i = 0; i < 100000; i++) {
counter = privateCache.get('counter');
counter = rate*counter*(1 - counter);
privateCache.put('counter', counter);
}
end_time = System.currentTimeMillis();
elapsed_time = end_time - start_time;
LoggerFactory.getLogger("org.openhab.core.automation.groovy").info("Performance Test: Groovy ran in ".concat(elapsed_time.toString()).concat(" milliseconds"));
JS Test 1: 270ms average
var counter = 0.2;
var rate = 3.54409;
var start_time, end_time, elapsed_time;
start_time = new Date().getTime();
cache.private.put('counter', counter);
for (let i = 0; i < 100000; i++) {
counter = cache.private.get('counter');
counter = rate*counter*(1 - counter);
cache.private.put('counter', counter);
}
end_time = new Date().getTime();
elapsed_time = end_time - start_time;
console.info('Performance Test: JavaScript ran in '.concat(elapsed_time).concat(' milliseconds'));
Python Test 1: 3090ms average
from scope import cache
import time
counter = 0.2
rate = 3.54409
start_time = time.time_ns()
cache.privateCache.put('counter', counter)
for i in range(100000):
counter = cache.privateCache.get('counter');
counter = rate*counter*(1 - counter);
cache.privateCache.put('counter', counter);
end_time = time.time_ns()
elapsed_time = (end_time - start_time) // 1000000
print(f'Performance Test: Python ran in {elapsed_time} milliseconds')
Running time increases linearly with the number of loops, so the cache read/writes were an obvious culprit. I removed the cache code and run purely off internal variables, plus I had to up the loops to 1,000,000 to more accurately see the relative difference.
Groovy test 2: 7ms average 
import org.slf4j.LoggerFactory;
long elapsed_time;
long start_time = System.currentTimeMillis();
long end_time;
float counter = 0.2;
float rate = 3.54409;
for (int i = 0; i < 1000000; i++) {
counter = rate*counter*(1 - counter);
}
end_time = System.currentTimeMillis();
elapsed_time = end_time - start_time;
LoggerFactory.getLogger("org.openhab.core.automation.groovy").info("Performance Test: Groovy ran in ".concat(elapsed_time.toString()).concat(" milliseconds"));
JS Test 2: 98ms average
var counter = 0.2;
var rate = 3.54409;
var start_time, end_time, elapsed_time;
start_time = new Date().getTime();
for (let i = 0; i < 1000000; i++) {
counter = rate*counter*(1 - counter);
}
end_time = new Date().getTime();
elapsed_time = end_time - start_time;
console.info('Performance Test: JavaScript ran in '.concat(elapsed_time).concat(' milliseconds'));
Python Test 2: 917ms average
import time
counter = 0.2
rate = 3.54409
start_time = time.time_ns()
for i in range(1000000):
counter = rate*counter*(1 - counter);
end_time = time.time_ns()
elapsed_time = (end_time - start_time) // 1000000
print(f'Performance Test: Python ran in {elapsed_time} milliseconds')
So the relative difference is still quite similar between Python and JS, albeit in this very artificial case. But finally Groovy shows an interesting use case, if you have some extremely math heavy script.