//
// wota_benchmark.js
//
// Usage in QuickJS:
//     qjs wota_benchmark.js
//
// Prerequisite:
     var wota = use('wota');
     var os   = use('os');
// or otherwise ensure `wota` and `os` are available.
// Make sure wota_benchmark.js is loaded after wota.js or combined with it.
//

// Helper to run a function repeatedly and measure total time in seconds.
// Returns elapsed time in seconds.
function measureTime(fn, iterations) {
    let t1 = os.now();
    for (let i = 0; i < iterations; i++) {
        fn();
    }
    let t2 = os.now();
    return t2 - t1;
}

// We'll define a function that does `encode -> decode` for a given value:
function roundTripWota(value) {
    let encoded = wota.encode(value);
    let decoded = wota.decode(encoded);
    // Not doing a deep compare here, just measuring performance.
    // (We trust the test suite to verify correctness.)
}

// A small suite of data we want to benchmark. Each entry includes:
//   name: label for printing
//   data: the test value(s) to encode/decode
//   iterations: how many times to loop
//
// You can tweak these as you like for heavier or lighter tests.
def benchmarks = [
  {
    name: "Small Integers",
    data: [0, 42, -1, 2023],
    iterations: 100000
  },
  {
    name: "Strings (short, emoji)",
    data: ["Hello, Wota!", "short", "Emoji: \u{1f600}\u{1f64f}"],
    iterations: 100000
  },
  {
    name: "Small Objects",
    data: [
      { a:1, b:2.2, c:"3", d:false },
      { x:42, y:null, z:"test" }
    ],
    iterations: 50000
  },
  {
    name: "Nested Arrays",
    data: [ [ [ [1,2], [3,4] ] ], [[[]]], [1, [2, [3, [4]]]] ],
    iterations: 50000
  },
  {
    name: "Large Array (1k numbers)",
    // A thousand random numbers
    data: [ Array.from({length:1000}, (_, i) => i * 0.5) ],
    iterations: 1000
  },
  {
    name: "Large Binary Blob (256KB)",
    // A 256KB ArrayBuffer
    data: [ new Uint8Array(256 * 1024).buffer ],
    iterations: 200
  }
];

// Print a header
log.console("Wota Encode/Decode Benchmark");
log.console("===================\n");

// We'll run each benchmark scenario in turn.
for (let bench of benchmarks) {
    // We'll measure how long it takes to do 'iterations' *for each test value*
    // in bench.data. The total loop count is `bench.iterations * bench.data.length`.
    // Then we compute an overall encode+decode throughput (ops/s).
    let totalIterations = bench.iterations * bench.data.length;
    
    // We'll define a function that does a roundTrip for *each* data item in bench.data
    // to measure in one loop iteration. Then we multiply by bench.iterations.
    function runAllData() {
        for (let val of bench.data) {
            roundTripWota(val);
        }
    }

    let elapsedSec = measureTime(runAllData, bench.iterations);
    let opsPerSec  = (totalIterations / elapsedSec).toFixed(1);

    log.console(`${bench.name}:`);
    log.console(`  Iterations: ${bench.iterations} × ${bench.data.length} data items = ${totalIterations}`);
    log.console(`  Elapsed:    ${elapsedSec.toFixed(3)} s`);
    log.console(`  Throughput: ${opsPerSec} encode+decode ops/sec\n`);
}

// All done
log.console("Benchmark completed.\n");
