Are you thinking this for general JS interpretation or just for crypto operations?
I meant it for general JS interpretation, but crypto operations are probably at the top range.
Note that the numbers I wrote were based on my intuition from seeing a few examples. Maybe my impression was biased due to the slow JS candid implementation.
To get more concrete numbers, I did a small experiment: a program that computes sum((i % 100)^2)
for all 0 <= i < 1M
. The expression was chosen to make it difficult for the compiler to optimize it away.
Here are the results:
- Rust: instructions: 13_761_694, sum: 3_283_500_000
- Motoko: instructions: 92_001_970, sum: 3_283_500_000
- Azle: instructions: 1_341_172_853, sum: 3_283_500_000
In this experiment Azle is 97x slower than Rust and 14x slower than Motoko.
I corrected 100x-1000x
to 10x-100x
in my post based on these results.
At least the QuickJS benchmarks put it about 35x less performant than JIT V8.
Assuming that V8 is close to native, I wonder if there is a factor of ~3x that’s missing here?
Attaching the source code of programs in case anyone wants to double check.
#[ic_cdk::query]
fn bench() -> String {
let mut sum: i64 = 0;
for i in 0..1_000_000 {
sum += (i % 100) * (i % 100);
}
format!("instructions: {}, sum: {}", ic_cdk::api::performance_counter(0), sum)
}
import IC "mo:base/ExperimentalInternetComputer";
import Nat64 "mo:base/Nat64";
actor {
public query func bench() : async Text {
var sum : Nat64 = 0;
var i: Nat64 = 0;
while (i < 1_000_000) {
sum += (i % 100) * (i % 100);
i += 1;
};
let instructions = IC.performanceCounter(0);
return "instructions: " # Nat64.toText(instructions) # ", sum: " # Nat64.toText(sum);
};
};
import { IDL, query, update, instructionCounter } from 'azle';
export default class {
@query([], IDL.Text)
bench(): string {
let sum = 0;
for (let i = 0; i < 1_000_000; ++i) {
sum += (i % 100) * (i % 100);
}
let instructions = instructionCounter(0);
return `instructions: ${instructions}, sum: ${sum}`;
}
}