// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

// This files contains methods for benchmarking Kernel binary serialization
// and deserialization routines.

import 'package:kernel/ast.dart';
import 'package:kernel/binary/ast_from_binary.dart';
import 'package:kernel/binary/ast_to_binary.dart';

import 'dart:io';
import 'dart:math';
import 'dart:typed_data';

final usage = '''
Usage: binary_bench.dart [--golem|--raw] <Benchmark> <SourceDill>

Benchmark can be one of: ${benchmarks.keys.join(', ')}
''';

typedef void Benchmark(Uint8List bytes);

final benchmarks = <String, Benchmark>{
  'AstFromBinaryEager': (Uint8List bytes) {
    return _benchmarkAstFromBinary(bytes, eager: true);
  },
  'AstFromBinaryLazy': (Uint8List bytes) {
    return _benchmarkAstFromBinary(bytes, eager: false);
  },
  'AstToBinary': (Uint8List bytes) {
    return _benchmarkAstToBinary(bytes);
  },
};

Benchmark? benchmark;
late File sourceDill;
bool forGolem = false;
bool forRaw = false;

void main(List<String> args) async {
  if (!_parseArgs(args)) {
    print(usage);
    exit(-1);
  }

  final bytes = sourceDill.readAsBytesSync();
  benchmark!(bytes);
}

const warmupIterations = 100;
const benchmarkIterations = 50;

void _benchmarkAstFromBinary(Uint8List bytes, {bool eager = true}) {
  final sw = new Stopwatch()..start();
  _fromBinary(bytes, eager: eager);
  final coldRunUs = sw.elapsedMicroseconds;
  sw.reset();

  for (var i = 0; i < warmupIterations; i++) {
    _fromBinary(bytes, eager: eager);
  }
  final warmupUs = sw.elapsedMicroseconds / warmupIterations;

  final runsUs =
      new List<int>.filled(benchmarkIterations, /* dummy value = */ 0);
  for (var i = 0; i < benchmarkIterations; i++) {
    sw.reset();
    _fromBinary(bytes, eager: eager);
    runsUs[i] = sw.elapsedMicroseconds;
  }

  final nameSuffix = eager ? 'Eager' : 'Lazy';
  new BenchmarkResult('AstFromBinary${nameSuffix}', coldRunUs, warmupUs, runsUs)
      .report();
}

void _benchmarkAstToBinary(Uint8List bytes) {
  final p = _fromBinary(bytes, eager: true);
  final sw = new Stopwatch()..start();
  _toBinary(p);
  final coldRunUs = sw.elapsedMicroseconds;
  sw.reset();

  for (var i = 0; i < warmupIterations; i++) {
    _toBinary(p);
  }
  final warmupUs = sw.elapsedMicroseconds / warmupIterations;

  final runsUs =
      new List<int>.filled(benchmarkIterations, /* dummy value = */ 0);
  for (var i = 0; i < benchmarkIterations; i++) {
    sw.reset();
    _toBinary(p);
    runsUs[i] = sw.elapsedMicroseconds;
  }

  new BenchmarkResult('AstToBinary', coldRunUs, warmupUs, runsUs).report();
}

class BenchmarkResult {
  final String name;
  final int coldRunUs;
  final double warmupUs;
  final List<int> runsUs;

  BenchmarkResult(this.name, this.coldRunUs, this.warmupUs, this.runsUs);

  static T add<T extends num>(T x, T y) => x + y as T;

  void report() {
    runsUs.sort();

    int P(int p) => runsUs[((runsUs.length - 1) * (p / 100)).ceil()];

    final sum = runsUs.reduce(add);
    final avg = sum / runsUs.length;
    final min = runsUs.first;
    final max = runsUs.last;
    final std =
        sqrt(runsUs.map((v) => pow(v - avg, 2)).reduce(add) / runsUs.length);

    if (forGolem) {
      print('${name}(RunTimeRaw): ${avg} us.');
      print('${name}P50(RunTimeRaw): ${P(50)} us.');
      print('${name}P90(RunTimeRaw): ${P(90)} us.');
    } else if (forRaw) {
      runsUs.forEach(print);
    } else {
      print('${name}Cold: ${coldRunUs} us');
      print('${name}Warmup: ${warmupUs} us');
      print('${name}: ${avg} us.');
      final prefix = '-' * name.length;
      print('${prefix}> Range: ${min}...${max} us.');
      print('${prefix}> Std Dev: ${std.toStringAsFixed(2)}');
      print('${prefix}> 50th percentile: ${P(50)} us.');
      print('${prefix}> 90th percentile: ${P(90)} us.');
    }
  }
}

bool _parseArgs(List<String> args) {
  if (args.length != 2 && args.length != 3) {
    return false;
  }

  if (args[0] == '--golem') {
    if (args.length != 3) {
      return false;
    }
    forGolem = true;
    args = args.skip(1).toList(growable: false);
  } else if (args[0] == '--raw') {
    if (args.length != 3) {
      return false;
    }
    forRaw = true;
    args = args.skip(1).toList(growable: false);
  }

  benchmark = benchmarks[args[0]];
  if (benchmark == null) {
    return false;
  }

  sourceDill = new File(args[1]);
  if (!sourceDill.existsSync()) {
    return false;
  }

  return true;
}

Component _fromBinary(Uint8List bytes, {eager = true}) {
  var component = new Component();
  new BinaryBuilder(bytes, filename: 'filename', disableLazyReading: eager)
      .readSingleFileComponent(component);
  return component;
}

class SimpleSink implements Sink<List<int>> {
  final List<List<int>> chunks = <List<int>>[];

  @override
  void add(List<int> chunk) {
    chunks.add(chunk);
  }

  @override
  void close() {}
}

void _toBinary(Component p) {
  new BinaryPrinter(new SimpleSink()).writeComponentFile(p);
}
