// Copyright (c) 2021, 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.

import 'dart:collection';

import 'package:benchmark_harness/benchmark_harness.dart';

// Benchmark for polymorphic map copying.
//
// The set of benchmarks compares the cost of copying default Maps
// (LinkedHashMaps) and HashMaps, for small and large maps.
//
// The maps have a key type `Object?`, since we want to use Strings, ints and
// user-defined types.  The class `Thing` is a used-defined type with an
// inexpensive hashCode operation. String keys are interesting because they are
// quite common, and are special-cased in the JavaScript runtime.
//
// Benchmarks have names following this pattern:
//
//     MapCopy.{Map,HashMap}.{String,Thing}.of.{Map,HashMap}.{N}
//     MapCopy.{Map,HashMap}.{String,Thing}.copyOf.{Map,HashMap}.{N}
//     MapCopy.{Map,HashMap}.{String,Thing}.fromEntries.{Map,HashMap}.{N}
//
// For example, MapCopy.Map.String.of.HashMap.2 would call
//
//     Map<Object, Object>.of(m)
//
// where `m` is a `HashMap<String, Object>` with 2 entries.
//
// The `copyOf` variant creates an empty map and populates it using `forEach`,
// so MapCopy.HashMap.Thing.copyOf.HashMap.100 would call:
//
//    HashMap<Object, Object> result = HashMap();
//    m.forEach((key, value) { result[key] = value; });
//
// where `m` is a `HashMap<Thing, Object>` with 100 entries.
//
// The `fromEntries` variant creates a map via `Map.fromEntries(other.entries)`.
//
// Benchmarks are run for small maps (e.g. 2 entries, names ending in `.2`) and
// 'large' maps (100 entries or `.100`). The benchmarks are normalized on the
// number of elements to make benchmarks with different input sizes more
// comparable.

abstract class Benchmark<K> extends BenchmarkBase {
  final String targetKind; // 'Map' or 'HashMap'.
  late final String keyKind = _keyKind(K); // 'String' or 'Thing' or 'int'.
  final String methodKind; // 'of' or 'copyOf' or 'fromEntries'.
  final String sourceKind; // 'Map' or 'HashMap'.
  final int length;
  final List<Map<Object?, Object>> inputs = [];

  Benchmark(this.targetKind, this.methodKind, this.sourceKind, this.length)
    : super(
        'MapCopy.$targetKind.${_keyKind(K)}.$methodKind.$sourceKind'
        '.$length',
      );

  static String _keyKind(Type type) {
    if (type == String) return 'String';
    if (type == int) return 'int';
    if (type == Thing) return 'Thing';
    throw UnsupportedError('Unsupported type $type');
  }

  /// Override this method with one that will copy [input] to [output].
  void copy();

  @override
  void setup() {
    // Ensure setup() is idempotent.
    if (inputs.isNotEmpty) return;

    const totalEntries = 1000;

    int totalLength = 0;
    while (totalLength < totalEntries) {
      final sample = makeSample();
      inputs.add(sample);
      totalLength += sample.length;
    }

    // Sanity checks.
    for (var sample in inputs) {
      if (sample.length != length) throw 'Wrong length: $length $sample';
    }
    if (totalLength != totalEntries) {
      throw 'totalLength $totalLength != expected $totalEntries';
    }
  }

  int _sequence = 0;

  Map<Object?, Object> makeSample() {
    late final Map<K, Object> sample;
    if (sourceKind == 'Map') sample = {};
    if (sourceKind == 'HashMap') sample = HashMap();
    for (int i = 1; i <= length; i++) {
      _sequence = (_sequence + 119) & 0x1ffffff;
      final K key = makeKey(_sequence);
      sample[key] = i;
    }
    return sample;
  }

  K makeKey(int i) {
    if (keyKind == 'String') return 'key-$i' as K;
    if (keyKind == 'int') return i as K;
    if (keyKind == 'Thing') return Thing() as K;
    throw UnsupportedError('Unsupported type $K');
  }

  @override
  void run() {
    for (var sample in inputs) {
      input = sample;
      copy();
    }
    if (output.length != inputs.first.length) throw 'Bad result: $output';
  }
}

class Thing {
  static int _counter = 0;
  final int _index;
  Thing() : _index = ++_counter;

  @override
  bool operator ==(Object other) => other is Thing && _index == other._index;

  @override
  int get hashCode => _index;
}

// All the 'copy' methods use [input] and [output] rather than a parameter and
// return value to avoid the possibility of a parametric covariance type check
// in the call sequence.
Map<Object?, Object> input = {};
var output;

class BaselineBenchmark extends Benchmark<String> {
  BaselineBenchmark(int length) : super('Map', 'baseline', 'Map', length);

  @override
  void copy() {
    // Dummy 'copy' to measure overhead of benchmarking loops.
    output = input;
  }
}

class MapOfBenchmark<K> extends Benchmark<K> {
  MapOfBenchmark(String sourceKind, int length)
    : super('Map', 'of', sourceKind, length);

  @override
  void copy() {
    output = Map<Object?, Object>.of(input);
  }
}

class HashMapOfBenchmark<K> extends Benchmark<K> {
  HashMapOfBenchmark(String sourceKind, int length)
    : super('HashMap', 'of', sourceKind, length);

  @override
  void copy() {
    output = HashMap<Object?, Object>.of(input);
  }
}

class MapCopyOfBenchmark<K> extends Benchmark<K> {
  MapCopyOfBenchmark(String sourceKind, int length)
    : super('Map', 'copyOf', sourceKind, length);

  @override
  void copy() {
    final map = <Object?, Object>{};
    input.forEach((k, v) {
      map[k] = v;
    });
    output = map;
  }
}

class HashMapCopyOfBenchmark<K> extends Benchmark<K> {
  HashMapCopyOfBenchmark(String sourceKind, int length)
    : super('HashMap', 'copyOf', sourceKind, length);

  @override
  void copy() {
    final map = HashMap<Object?, Object>();
    input.forEach((k, v) {
      map[k] = v;
    });
    output = map;
  }
}

class MapFromEntriesBenchmark<K> extends Benchmark<K> {
  MapFromEntriesBenchmark(String sourceKind, int length)
    : super('Map', 'fromEntries', sourceKind, length);

  @override
  void copy() {
    output = Map<Object?, Object>.fromEntries(input.entries);
  }
}

class HashMapFromEntriesBenchmark<K> extends Benchmark<K> {
  HashMapFromEntriesBenchmark(String sourceKind, int length)
    : super('HashMap', 'fromEntries', sourceKind, length);

  @override
  void copy() {
    output = HashMap<Object?, Object>.fromEntries(input.entries);
  }
}

/// Use the common methods for many different kinds of Map to make the calls in
/// the runtime implementation polymorphic.
void pollute() {
  final Map<String, Object> m1 = Map.of({'hello': 66});
  final Map<String, Object> m2 = HashMap.of(m1);
  final Map<int, Object> m3 = Map.of({1: 66});
  final Map<int, Object> m4 = HashMap.of({1: 66});
  final Map<Object, Object> m5 = Map.identity()
    ..[Thing()] = 1
    ..[Thing()] = 2;
  final Map<Object, Object> m6 = HashMap.identity()
    ..[Thing()] = 1
    ..[Thing()] = 2;
  final Map<Object, Object> m7 = UnmodifiableMapView(m1);
  final Map<Object, Object> m8 = UnmodifiableMapView(m2);
  final Map<Object, Object> m9 = UnmodifiableMapView(m3);
  final Map<Object, Object> m10 = UnmodifiableMapView(m4);

  int c = 0;
  for (final m in [m1, m2, m3, m4, m5, m6, m7, m8, m9, m10]) {
    final Map<Object, Object> d1 = Map.of(m);
    final Map<Object, Object> d2 = HashMap.of(m);
    // ignore: prefer_collection_literals
    final Map<Object, Object> d3 = Map()..addAll(m);
    final Map<Object, Object> d4 = {...m, ...m};
    final Map<Object, Object> d5 = HashMap()..addAll(m);
    final Map<Object, Object> d6 = Map.identity()..addAll(m);
    final Map<Object, Object> d7 = HashMap.identity()..addAll(m);
    final Map<Object, Object> d8 = Map.fromEntries(m.entries);
    final Map<Object, Object> d9 = HashMap.fromEntries(m.entries);
    for (final z in [d1, d2, d3, d4, d5, d6, d7, d8, d9]) {
      z.forEach((k, v) {
        c++;
      });
    }
  }
  const totalElements = 108;
  if (c != totalElements) throw StateError('c: $c != $totalElements');
}

/// Command-line arguments:
///
/// `--baseline`: Run additional benchmarks to measure the benchmarking loop
/// component.
///
/// `--cross`: Run additional benchmarks for copying between Map and
/// HashMap.
///
/// `--int`: Run additional benchmarks with `int` keys.
///
/// `--1`: Run additional benchmarks for singleton maps.
///
/// `--all`: Run all benchmark variants.
void main(List<String> commandLineArguments) {
  final arguments = [...commandLineArguments];

  bool includeBaseline = false;
  final Set<String> kinds = {'same'};
  final Set<String> types = {'String', 'Thing'};
  final Set<int> sizes = {2, 100};

  if (arguments.remove('--reset')) {
    kinds.clear();
    types.clear();
    sizes.clear();
  }

  if (arguments.remove('--baseline')) includeBaseline = true;
  if (arguments.remove('--cross')) kinds.add('cross');

  if (arguments.remove('--string')) types.add('String');
  if (arguments.remove('--thing')) types.add('Thing');
  if (arguments.remove('--int')) types.add('int');

  if (arguments.remove('--1')) sizes.add(1);
  if (arguments.remove('--2')) sizes.add(2);
  if (arguments.remove('--100')) sizes.add(100);

  if (arguments.remove('--all')) {
    kinds.addAll(['baseline', 'same', 'cross']);
    types.addAll(['String', 'Thing', 'int']);
    sizes.addAll([1, 2, 100]);
  }

  if (arguments.isNotEmpty) {
    throw ArgumentError('Unused command line arguments: $arguments');
  }

  if (kinds.isEmpty) kinds.add('same');
  if (types.isEmpty) types.add('String');
  if (sizes.isEmpty) sizes.add(2);

  List<Benchmark> makeBenchmarks<K>(int length) {
    return [
      // Map from Map
      if (kinds.contains('same')) ...[
        MapOfBenchmark<K>('Map', length),
        MapCopyOfBenchmark<K>('Map', length),
        MapFromEntriesBenchmark<K>('Map', length),
      ],
      // Map from HashMap
      if (kinds.contains('cross')) ...[
        MapOfBenchmark<K>('HashMap', length),
        MapCopyOfBenchmark<K>('HashMap', length),
        MapFromEntriesBenchmark<K>('HashMap', length),
      ],
      // HashMap from HashMap
      if (kinds.contains('same')) ...[
        HashMapOfBenchmark<K>('HashMap', length),
        HashMapCopyOfBenchmark<K>('HashMap', length),
        HashMapFromEntriesBenchmark<K>('HashMap', length),
      ],
      // HashMap from Map
      if (kinds.contains('cross')) ...[
        HashMapOfBenchmark<K>('Map', length),
        HashMapCopyOfBenchmark<K>('Map', length),
        HashMapFromEntriesBenchmark<K>('Map', length),
      ],
    ];
  }

  List<Benchmark> makeBenchmarksForLength(int length) {
    return [
      if (includeBaseline) BaselineBenchmark(length),
      if (types.contains('String')) ...makeBenchmarks<String>(length),
      if (types.contains('Thing')) ...makeBenchmarks<Thing>(length),
      if (types.contains('int')) ...makeBenchmarks<int>(length),
    ];
  }

  final benchmarks = [
    for (final length in sizes) ...makeBenchmarksForLength(length),
  ];

  // Warmup all benchmarks to ensure JIT compilers see full polymorphism.
  for (var benchmark in benchmarks) {
    pollute();
    benchmark.setup();
  }

  for (var benchmark in benchmarks) {
    pollute();
    benchmark.warmup();
  }

  for (var benchmark in benchmarks) {
    // `report` calls `setup`, but `setup` is idempotent.
    benchmark.report();
  }
}
