Run details:
Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Ubuntu Chromium/75.0.3770.90 Chrome/75.0.3770.90 Safari/537.36
Chromium 75
Ubuntu
Desktop
5 years ago
Test name Executions per second
v0 5065.7 Ops/sec
v1 use strict 7812.1 Ops/sec
v1 8232.4 Ops/sec
tailcall 44140.8 Ops/sec
vanilla 47891.6 Ops/sec
iterative 62185.8 Ops/sec
Script Preparation code:
x
 
NNN = 100
function v0 () {
 function voidf(k) { return k(undefined); };
function pk(x, y) {
    console.log("pk", x, y);
    return voidf;
}
function trampoline(thunk) {
    // console.log('trampoline start', thunk)
    while (thunk && typeof thunk === "function") {
        // console.log('boing');
        thunk = thunk();
    }
    return thunk
}
function add(a, b) {
    return a + b;
}
function times(a, b) {
    return a * b;
}
let program =
(function( kxx ) {  return (function(  ) {  return (function( k ) {  return k ( (function( kk, factorial_0 ) {  return (function(  ) {  return (function( kxx ) {  return (function(  ) {  return (function( k ) {  return k ( (function( kk, t_3 ) {  return (function(  ) {  return (function( kxx ) {  return (function(  ) {  return factorial_0 ( (function( v ) {  return (function(  ) {  return (function( k ) {  return k ( NNN ) ;}) ( (function( v0 ) {  return (function(  ) {  return (function( k ) {  return k ( 1 ) ;}) ( (function( v1 ) {  return (function(  ) {  return v ( kxx, (function( kv ) {  return kv ( v0 ) ;}), (function( kv ) {  return kv ( v1 ) ;}) ) ;}) ;}) ) ;}) ;}) ) ;}) ;}) ) ;}) ;}) ( kk ) ;}) ;}) ) ;}) ( (function( v ) {  return (function(  ) {  return (function( k ) {  return (function(  ) {  factorial_0 = (function( k ) {  return k ( (function( kk, n_1, total_2 ) {  return (function(  ) {  return (function( k ) {  return (function( kpr ) {  return (function(  ) {  return n_1 ( (function( v0 ) {  return (function(  ) {  return (function( k ) {  return k ( 0 ) ;}) ( (function( v1 ) {  return kpr ( v0 === v1 ) ;}) ) ;}) ;}) ) ;}) ;}) ( (function( kif ) {  return /* if */ kif ? (function(  ) {  return total_2 ( k ) ;}) : (function(  ) {  return (function( kxx ) {  return (function(  ) {  return factorial_0 ( (function( v ) {  return (function(  ) {  return (function( kpr ) {  return (function(  ) {  return n_1 ( (function( v0 ) {  return (function(  ) {  return (function( k ) {  return k ( -1 ) ;}) ( (function( v1 ) {  return kpr ( add ( v0, v1 ) ) ;}) ) ;}) ;}) ) ;}) ;}) ( (function( v0 ) {  return (function(  ) {  return (function( kpr ) {  return (function(  ) {  return n_1 ( (function( v0 ) {  return (function(  ) {  return total_2 ( (function( v1 ) {  return kpr ( times ( v0, v1 ) ) ;}) ) ;}) ;}) ) ;}) ;}) ( (function( v1 ) {  return (function(  ) {  return v ( kxx, (function( kv ) {  return kv ( v0 ) ;}), (function( kv ) {  return kv ( v1 ) ;}) ) ;}) ;}) ) ;}) ;}) ) ;}) ;}) ) ;}) ;}) ( k ) ;}) ;}) ) ;}) ( kk ) ;}) ;}) ) ;}); return k ( voidf ) ;}) ;}) ( (function( v0 ) {  return (function(  ) {  return v ( kxx, (function( kv ) {  return kv ( v0 ) ;}) ) ;}) ;}) ) ;}) ;}) ) ;}) ;}) ( kk ) ;}) ;}) ) ;}) ( (function( v ) {  return (function(  ) {  return voidf ( (function( v0 ) {  return (function(  ) {  return v ( kxx, (function( kv ) {  return kv ( v0 ) ;}) ) ;}) ;}) ) ;}) ;}) ) ;}) ;})
;
function output(x) {
    pk('output', x);
    return function() {};
}
trampoline(function() {return program (output);}); 
}
function v1strict() {
"use strict";
function voidf(k) { return k(undefined); };
function pk() {
    console.log.apply(console, arguments);
}
function trampoline(thunk) {
    // console.log('trampoline start', thunk)
    while (thunk && typeof thunk === "function") {
        // console.log('boing');
        thunk = thunk();
    }
    return thunk
}
function prepend(v, a) {
    // a.slice().unshift(0); // avoid mutation with copy
    a.unshift(v);
    return a;
}
function apply(func, args) {
    return func.apply(this, args);
}
function add(a, b) {
    return a + b;
}
function times(a, b) {
    return a * b;
}
let program =
(function( k ) {  return (function( k ) {  return k ( (function( k, fact_0 ) {  return (function( k ) {  return (function( k ) {  return k ( (function( k, t_3 ) {  return (function( k ) {  return fact_0 ( (function( v ) {  return (function( k ) {  return k ( NNN ) ;}) ( (function( v0 ) {  return (function( k ) {  return k ( 1 ) ;}) ( (function( v1 ) {  return (function(  ) {  return v ( k, (function( kv ) {  return kv ( v0 ) ;}), (function( kv ) {  return kv ( v1 ) ;}) ) ;}) ;}) ) ;}) ) ;}) ) ;}) ( k ) ;}) ) ;}) ( (function( v ) {  return (function( k ) {  return (function(  ) {  fact_0 = (function( k ) {  return k ( (function( k, n_1, total_2 ) {  return (function( k ) {  return (function( k ) {  return n_1 ( (function( v0 ) {  return (function( k ) {  return k ( 0 ) ;}) ( (function( v1 ) {  return k ( v0 === v1 ) ;}) ) ;}) ) ;}) ( (function( kif ) {  return /* if */ kif ? (function(  ) {  return total_2 ( k ) ;}) : (function(  ) {  return (function( k ) {  return fact_0 ( (function( v ) {  return (function( k ) {  return n_1 ( (function( v0 ) {  return (function( k ) {  return k ( -1 ) ;}) ( (function( v1 ) {  return k ( add ( v0, v1 ) ) ;}) ) ;}) ) ;}) ( (function( v0 ) {  return (function( k ) {  return total_2 ( (function( v0 ) {  return n_1 ( (function( v1 ) {  return k ( times ( v0, v1 ) ) ;}) ) ;}) ) ;}) ( (function( v1 ) {  return (function(  ) {  return v ( k, (function( kv ) {  return kv ( v0 ) ;}), (function( kv ) {  return kv ( v1 ) ;}) ) ;}) ;}) ) ;}) ) ;}) ) ;}) ( k ) ;}) ;}) ) ;}) ( k ) ;}) ) ;}); return k ( voidf ) ;}) ;}) ( (function( v0 ) {  return (function(  ) {  return v ( k, (function( kv ) {  return kv ( v0 ) ;}) ) ;}) ;}) ) ;}) ) ;}) ( k ) ;}) ) ;}) ( (function( v ) {  return voidf ( (function( v0 ) {  return (function(  ) {  return v ( k, (function( kv ) {  return kv ( v0 ) ;}) ) ;}) ;}) ) ;}) ) ;})
;
function output(x) {
    pk('output', x);
    return function() {};
}
trampoline(function() {return program (output);}); 
}
function v1() {
 function voidf(k) { return k(undefined); };
function pk() {
    console.log.apply(console, arguments);
}
function trampoline(thunk) {
    // console.log('trampoline start', thunk)
    while (thunk && typeof thunk === "function") {
        // console.log('boing');
        thunk = thunk();
    }
    return thunk
}
function prepend(v, a) {
    // a.slice().unshift(0); // avoid mutation with copy
    a.unshift(v);
    return a;
}
function apply(func, args) {
    return func.apply(this, args);
}
function add(a, b) {
    return a + b;
}
function times(a, b) {
    return a * b;
}
let program =
(function( k ) {  return (function( k ) {  return k ( (function( k, fact_0 ) {  return (function( k ) {  return (function( k ) {  return k ( (function( k, t_3 ) {  return (function( k ) {  return fact_0 ( (function( v ) {  return (function( k ) {  return k ( NNN ) ;}) ( (function( v0 ) {  return (function( k ) {  return k ( 1 ) ;}) ( (function( v1 ) {  return (function(  ) {  return v ( k, (function( kv ) {  return kv ( v0 ) ;}), (function( kv ) {  return kv ( v1 ) ;}) ) ;}) ;}) ) ;}) ) ;}) ) ;}) ( k ) ;}) ) ;}) ( (function( v ) {  return (function( k ) {  return (function(  ) {  fact_0 = (function( k ) {  return k ( (function( k, n_1, total_2 ) {  return (function( k ) {  return (function( k ) {  return n_1 ( (function( v0 ) {  return (function( k ) {  return k ( 0 ) ;}) ( (function( v1 ) {  return k ( v0 === v1 ) ;}) ) ;}) ) ;}) ( (function( kif ) {  return /* if */ kif ? (function(  ) {  return total_2 ( k ) ;}) : (function(  ) {  return (function( k ) {  return fact_0 ( (function( v ) {  return (function( k ) {  return n_1 ( (function( v0 ) {  return (function( k ) {  return k ( -1 ) ;}) ( (function( v1 ) {  return k ( add ( v0, v1 ) ) ;}) ) ;}) ) ;}) ( (function( v0 ) {  return (function( k ) {  return total_2 ( (function( v0 ) {  return n_1 ( (function( v1 ) {  return k ( times ( v0, v1 ) ) ;}) ) ;}) ) ;}) ( (function( v1 ) {  return (function(  ) {  return v ( k, (function( kv ) {  return kv ( v0 ) ;}), (function( kv ) {  return kv ( v1 ) ;}) ) ;}) ;}) ) ;}) ) ;}) ) ;}) ( k ) ;}) ;}) ) ;}) ( k ) ;}) ) ;}); return k ( voidf ) ;}) ;}) ( (function( v0 ) {  return (function(  ) {  return v ( k, (function( kv ) {  return kv ( v0 ) ;}) ) ;}) ;}) ) ;}) ) ;}) ( k ) ;}) ) ;}) ( (function( v ) {  return voidf ( (function( v0 ) {  return (function(  ) {  return v ( k, (function( kv ) {  return kv ( v0 ) ;}) ) ;}) ;}) ) ;}) ) ;})
;
function output(x) {
    pk('output', x);
    return function() {};
}
trampoline(function() {return program (output);}); 
}
function vanilla() {
   function factorial (n) {
        return n === 0 ? 1 : n * factorial(n -1); 
   }
  
  console.log(factorial(NNN));
}
function tailcall() {
   function factorial (n, total) {
        return n === 0 ? total : factorial(n - 1, total * n); 
   }
  
  console.log(factorial(NNN, 1))
}
function iterative() {
function sFact(num)
{
    var rval=1;
    for (var i = 2; i <= num; i++)
        rval = rval * i;
    return rval;
}
  console.log(sFact(NNN)); 
}
Tests:
  • v0

     
    v0()
  • v1 use strict

     
    v1strict()
  • v1

     
    v1()
  • tailcall

     
    tailcall()
  • vanilla

     
    vanilla()
  • iterative

     
    iterative()