| // 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(); | 
 |   } | 
 | } |