// Copyright (c) 2020, 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 'dart:typed_data';
import 'package:benchmark_harness/benchmark_harness.dart';

// Benchmark for polymorphic list copying.
//
// Each benchmark creates a list from an Iterable. There are many slightly
// different ways to do this.
//
// In each benchmark the call site is polymorphic in the input type to simulate
// the behaviour of library methods in the context of a large application. The
// input lists are skewed heavily to the default growable list. This attempts to
// model 'real world' copying of 'ordinary' lists.
//
// The benchmarks are run for small lists (2 elements, names ending in
// `.2`) and 'large' lists (100 elements or `.100`). The benchmarks are
// normalized on the number of elements to make the input sizes comparable.
//
// Most inputs have type `Iterable<num>`, but contain only `int` values. This
// allows is to compare the down-conversion versions of copying where each
// element must be checked.

class Benchmark extends BenchmarkBase {
  final int length;
  final Function() copy;

  final List<Iterable<num>> inputs = [];

  Benchmark(String name, this.length, this.copy)
      : super('ListCopy.$name.$length');

  void setup() {
    // Ensure setup() is idempotent.
    if (inputs.isNotEmpty) return;
    List<num> base = List.generate(length, (i) => i + 1);
    List<Iterable<num>> makeVariants() {
      return [
        // Weight ordinary lists more.
        ...List.generate(19, (_) => List<num>.of(base)),

        base.toList(growable: false),
        List<num>.unmodifiable(base),
        UnmodifiableListView(base),
        base.reversed,
        String.fromCharCodes(List<int>.from(base)).codeUnits,
        Uint8List.fromList(List<int>.from(base)),
      ];
    }

    const elements = 10000;
    int totalLength = 0;
    while (totalLength < elements) {
      var variants = makeVariants();
      inputs.addAll(variants);
      totalLength +=
          variants.fold<int>(0, (sum, iterable) => sum + iterable.length);
    }

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

  void run() {
    for (var sample in inputs) {
      input = sample;
      // Unroll loop 10 times to reduce loop overhead, which is about 15% for
      // the fastest short input benchmarks.
      copy();
      copy();
      copy();
      copy();
      copy();
      copy();
      copy();
      copy();
      copy();
      copy();
    }
    if (output.length != inputs.first.length) throw 'Bad result: $output';
  }
}

// All the 'copy' methods use [input] and [output] rather than a parameter and
// return value to avoid any possibility of type check in the call sequence.
Iterable<num> input = const [];
var output;

List<Benchmark> makeBenchmarks(int length) => [
      Benchmark('toList', length, () {
        output = input.toList();
      }),
      Benchmark('toList.fixed', length, () {
        output = input.toList(growable: false);
      }),
      Benchmark('List.of', length, () {
        output = List<num>.of(input);
      }),
      Benchmark('List.of.fixed', length, () {
        output = List<num>.of(input, growable: false);
      }),
      Benchmark('List.num.from', length, () {
        output = List<num>.from(input);
      }),
      Benchmark('List.int.from', length, () {
        output = List<int>.from(input);
      }),
      Benchmark('List.num.from.fixed', length, () {
        output = List<num>.from(input, growable: false);
      }),
      Benchmark('List.int.from.fixed', length, () {
        output = List<int>.from(input, growable: false);
      }),
      Benchmark('List.num.unmodifiable', length, () {
        output = List<num>.unmodifiable(input);
      }),
      Benchmark('List.int.unmodifiable', length, () {
        output = List<int>.unmodifiable(input);
      }),
      Benchmark('spread.num', length, () {
        output = <num>[...input];
      }),
      Benchmark('spread.int', length, () {
        output = <int>[...input];
      }),
    ];

main() {
  var benchmarks = [...makeBenchmarks(2), ...makeBenchmarks(100)];

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

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

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