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