// Copyright (c) 2024, 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 'dart:io';
import 'dart:math';
import 'dart:typed_data';

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

import '../tool/compile.dart' as compile;

final String usage = '''
Usage: kernel_binary_bench.dart [--golem|--raw] {--metadata|--onlyCold} <Benchmark> <SourceDill>

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

typedef void Benchmark(Uint8List bytes);

final Map<String, Benchmark> benchmarks = {
  '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;
bool metadataAware = false;
bool onlyCold = false;

void main(List<String> args) async {
  if (args.length == 1 && args[0] == "--compile") {
    // Allow - although in practise unused - to go to a bigger target (in this
    // case the compile target) - in order to get a more real polymorphic
    // potential (especially for AOT compiles).
    return await compile.main(args);
  }
  if (!_parseArgs(args)) {
    print(usage);
    exit(-1);
  }

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

int warmupIterations = 100;
int benchmarkIterations = 50;

void _benchmarkAstFromBinary(Uint8List bytes, {bool eager = true}) {
  final String nameSuffix = eager ? 'Eager' : 'Lazy';

  final Stopwatch sw = new Stopwatch()..start();
  _fromBinary(bytes, eager: eager);
  final int coldRunUs = sw.elapsedMicroseconds;
  sw.reset();
  if (onlyCold) {
    new BenchmarkResult('AstFromBinary${nameSuffix}', coldRunUs,
        coldRunUs.toDouble(), [coldRunUs]).report();
    return;
  }

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

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

  new BenchmarkResult('AstFromBinary${nameSuffix}', coldRunUs, warmupUs, runsUs)
      .report();
}

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

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

  final List<int> runsUs =
      new List<int>.filled(benchmarkIterations, /* dummy value = */ 0);
  for (int 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 int sum = runsUs.reduce(add);
    final double avg = sum / runsUs.length;
    final int min = runsUs.first;
    final int max = runsUs.last;
    final double 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 String 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> argsOrg) {
  List<String> trimmedArgs = [];
  for (String arg in argsOrg) {
    if (arg == "--golem") {
      forGolem = true;
    } else if (arg == "--raw") {
      forRaw = true;
    } else if (arg == "--metadata") {
      metadataAware = true;
    } else if (arg == "--onlyCold") {
      onlyCold = true;
    } else if (arg.startsWith("--warmups=")) {
      warmupIterations = int.parse(arg.substring("--warmups=".length));
    } else if (arg.startsWith("--iterations=")) {
      benchmarkIterations = int.parse(arg.substring("--iterations=".length));
    } else {
      trimmedArgs.add(arg);
    }
  }

  if (trimmedArgs.length != 2) {
    return false;
  }
  if (forGolem && forRaw) {
    return false;
  }

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

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

  return true;
}

Component _fromBinary(Uint8List bytes,
    {required bool eager, bool verbose = false}) {
  Component component = new Component();
  if (metadataAware) {
    // This is currently (October 2024) what VmTarget.configureComponent does.
    component.metadata.putIfAbsent(
        CallSiteAttributesMetadataRepository.repositoryTag,
        () => new CallSiteAttributesMetadataRepository());
    BinaryBuilderWithMetadata builder = new BinaryBuilderWithMetadata(bytes,
        filename: 'filename', disableLazyReading: eager);
    builder.readComponent(component);
    if (verbose) {
      // No current verbose output.
    }
  } else {
    new BinaryBuilder(bytes, filename: 'filename', disableLazyReading: eager)
        .readComponent(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);
}

// The below is copied from package:vm so to test metadata properly without
// depending on package:vm.

/// Metadata for annotating call sites with various attributes.
class CallSiteAttributesMetadata {
  final DartType receiverType;

  const CallSiteAttributesMetadata({required this.receiverType});

  @override
  String toString() =>
      "receiverType:${receiverType.toText(astTextStrategyForTesting)}";
}

/// Repository for [CallSiteAttributesMetadata].
class CallSiteAttributesMetadataRepository
    extends MetadataRepository<CallSiteAttributesMetadata> {
  static final repositoryTag = 'vm.call-site-attributes.metadata';

  @override
  final String tag = repositoryTag;

  @override
  final Map<TreeNode, CallSiteAttributesMetadata> mapping =
      <TreeNode, CallSiteAttributesMetadata>{};

  @override
  void writeToBinary(
      CallSiteAttributesMetadata metadata, Node node, BinarySink sink) {
    sink.writeDartType(metadata.receiverType);
  }

  @override
  CallSiteAttributesMetadata readFromBinary(Node node, BinarySource source) {
    final type = source.readDartType();
    return new CallSiteAttributesMetadata(receiverType: type);
  }
}
