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

/// Micro-benchmark for the [IOSink] returned by [File.openWrite].

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

import 'package:benchmark_harness/benchmark_harness.dart';

const numBytesToWrite = 200000; // Write 200KiB in all benchmarks runs.

/// Benchmark building a [numBytesToWrite] byte file a single byte at a time.
///
/// Based on https://github.com/dart-lang/sdk/issues/32874#issue-314022259
class BenchmarkManySmallAdds extends AsyncBenchmarkBase {
  late Directory _tempDir;
  late IOSink _ioSink;
  final _singleByte = Uint8List(1);

  BenchmarkManySmallAdds() : super('FileIOSink.Add.ManySmall');

  @override
  Future<void> setup() async {
    _tempDir = Directory.systemTemp.createTempSync();
    _ioSink = File(_tempDir.uri.resolve('many-small').toFilePath()).openWrite();
  }

  @override
  Future<void> teardown() async {
    await _ioSink.close();
    _tempDir.deleteSync(recursive: true);
  }

  @override
  Future<void> run() async {
    for (var i = 0; i < numBytesToWrite; ++i) {
      _ioSink.add(_singleByte);
    }
    await _ioSink.flush();
  }
}

/// Benchmark building a [numBytesToWrite] byte file with a single call to
/// [IOSink.add].
class BenchmarkOneLargeAdd extends AsyncBenchmarkBase {
  late final Directory _tempDir;
  late final IOSink _ioSink;
  final _largeData = Uint8List(numBytesToWrite);

  BenchmarkOneLargeAdd() : super('FileIOSink.Add.OneLarge');

  @override
  Future<void> setup() async {
    _tempDir = Directory.systemTemp.createTempSync();
    _ioSink = File(_tempDir.uri.resolve('one-large').toFilePath()).openWrite();
  }

  @override
  Future<void> teardown() async {
    await _ioSink.close();
    _tempDir.deleteSync(recursive: true);
  }

  @override
  Future<void> run() async {
    _ioSink.add(_largeData);
    await _ioSink.flush();
  }
}

/// Benchmark building a file by alternating calls to [IOSink.add] with large
/// and small amounts of data.
class BenchmarkAlternatingSizedAdd extends AsyncBenchmarkBase {
  late final Directory _tempDir;
  late final IOSink _ioSink;
  final _largeData = Uint8List(numBytesToWrite - 1);
  final _smallData = Uint8List(1);

  BenchmarkAlternatingSizedAdd() : super('FileIOSink.Add.AlternatingAddSize');

  @override
  Future<void> setup() async {
    _tempDir = Directory.systemTemp.createTempSync();
    _ioSink = File(
      _tempDir.uri.resolve('alternative-add-size').toFilePath(),
    ).openWrite();
  }

  @override
  Future<void> teardown() async {
    await _ioSink.close();
    _tempDir.deleteSync(recursive: true);
  }

  @override
  Future<void> run() async {
    _ioSink.add(_largeData);
    _ioSink.add(_smallData);
    await _ioSink.flush();
  }
}

void main() async {
  final benchmarks = [
    BenchmarkManySmallAdds(),
    BenchmarkOneLargeAdd(),
    BenchmarkAlternatingSizedAdd(),
  ];

  for (final benchmark in benchmarks) {
    await benchmark.report();
  }
}
