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

// @dart=2.9

import 'dart:async';
import 'dart:isolate';
import 'dart:math';

import 'package:meta/meta.dart';

import 'package:compiler/src/dart2js.dart' as dart2js_main;

class SpawnLatency {
  SpawnLatency(this.name);

  Future<ResultMessageLatency> run() async {
    final completerResult = Completer();
    final receivePort = ReceivePort()..listen(completerResult.complete);
    final isolateExitedCompleter = Completer<DateTime>();
    final onExitReceivePort = ReceivePort()
      ..listen((_) {
        isolateExitedCompleter.complete(DateTime.now());
      });
    final beforeSpawn = DateTime.now();
    await Isolate.spawn(
        isolateCompiler, StartMessageLatency(receivePort.sendPort, beforeSpawn),
        onExit: onExitReceivePort.sendPort,
        onError: onExitReceivePort.sendPort);
    final afterSpawn = DateTime.now();

    final ResultMessageLatency result = await completerResult.future;
    receivePort.close();
    final DateTime isolateExited = await isolateExitedCompleter.future;
    result.timeToExitUs = isolateExited.difference(beforeSpawn).inMicroseconds;
    result.timeToIsolateSpawnUs =
        afterSpawn.difference(beforeSpawn).inMicroseconds;
    onExitReceivePort.close();

    return result;
  }

  Future<AggregatedResultMessageLatency> measureFor(int minimumMillis) async {
    final minimumMicros = minimumMillis * 1000;
    final watch = Stopwatch()..start();
    final Metric toAfterIsolateSpawnUs = LatencyMetric('${name}ToAfterSpawn');
    final Metric toStartRunningCodeUs = LatencyMetric('${name}ToStartRunning');
    final Metric toFinishRunningCodeUs =
        LatencyMetric('${name}ToFinishRunning');
    final Metric toExitUs = LatencyMetric('${name}ToExit');
    while (watch.elapsedMicroseconds < minimumMicros) {
      final result = await run();
      toAfterIsolateSpawnUs.add(result.timeToIsolateSpawnUs);
      toStartRunningCodeUs.add(result.timeToStartRunningCodeUs);
      toFinishRunningCodeUs.add(result.timeToFinishRunningCodeUs);
      toExitUs.add(result.timeToExitUs);
    }
    return AggregatedResultMessageLatency(toAfterIsolateSpawnUs,
        toStartRunningCodeUs, toFinishRunningCodeUs, toExitUs);
  }

  Future<AggregatedResultMessageLatency> measure() async {
    await measureFor(500); // warm-up
    return measureFor(4000); // actual measurement
  }

  Future<void> report() async {
    final result = await measure();
    print(result);
  }

  final String name;
  RawReceivePort receivePort;
}

class Metric {
  Metric({@required this.prefix, @required this.suffix});

  void add(int value) {
    if (value > max) {
      max = value;
    }
    sum += value;
    sumOfSquares += value * value;
    count++;
  }

  double _average() => sum / count;
  double _rms() => sqrt(sumOfSquares / count);

  @override
  String toString() => '$prefix): ${_average()}$suffix\n'
      '${prefix}Max): $max$suffix\n'
      '${prefix}RMS): ${_rms()}$suffix';

  final String prefix;
  final String suffix;
  int max = 0;
  double sum = 0;
  double sumOfSquares = 0;
  int count = 0;
}

class LatencyMetric extends Metric {
  LatencyMetric(String name) : super(prefix: '$name(Latency', suffix: ' us.');
}

class StartMessageLatency {
  StartMessageLatency(this.sendPort, this.spawned);

  final SendPort sendPort;
  final DateTime spawned;
}

class ResultMessageLatency {
  ResultMessageLatency(
      {this.timeToStartRunningCodeUs,
      this.timeToFinishRunningCodeUs,
      this.deltaHeap});

  final int timeToStartRunningCodeUs;
  final int timeToFinishRunningCodeUs;
  final int deltaHeap;

  int timeToIsolateSpawnUs;
  int timeToExitUs;
}

class AggregatedResultMessageLatency {
  AggregatedResultMessageLatency(
    this.toAfterIsolateSpawnUs,
    this.toStartRunningCodeUs,
    this.toFinishRunningCodeUs,
    this.toExitUs,
  );

  @override
  String toString() => '''$toAfterIsolateSpawnUs
$toStartRunningCodeUs
$toFinishRunningCodeUs
$toExitUs''';

  final Metric toAfterIsolateSpawnUs;
  final Metric toStartRunningCodeUs;
  final Metric toFinishRunningCodeUs;
  final Metric toExitUs;
}

Future<void> isolateCompiler(StartMessageLatency start) async {
  final timeRunningCodeUs = DateTime.now();
  await runZoned(
      () => dart2js_main.internalMain(<String>[
            'benchmarks/IsolateSpawn/dart/helloworld.dart',
            '--libraries-spec=sdk/lib/libraries.json'
          ]),
      zoneSpecification: ZoneSpecification(
          print: (Zone self, ZoneDelegate parent, Zone zone, String line) {}));
  final timeFinishRunningCodeUs = DateTime.now();
  start.sendPort.send(ResultMessageLatency(
      timeToStartRunningCodeUs:
          timeRunningCodeUs.difference(start.spawned).inMicroseconds,
      timeToFinishRunningCodeUs:
          timeFinishRunningCodeUs.difference(start.spawned).inMicroseconds));
}

Future<void> main() async {
  await SpawnLatency('IsolateSpawn.Dart2JS').report();
}
