From 987a45da4ad27e2c9be2d36d1cf7635ba5ca1018 Mon Sep 17 00:00:00 2001 From: Brian Quinlan Date: Tue, 28 Feb 2023 20:40:40 +0000 Subject: [PATCH] [io] Add a benchmark for the IOSink returned by File.openWrite Change-Id: Ic27d24633a305d0567c19f3694b1a477b3a1eef2 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/285706 Commit-Queue: Brian Quinlan Reviewed-by: Alexander Markov --- benchmarks/FileIOSink/dart/FileIOSink.dart | 114 +++++++++++++++++++++ 1 file changed, 114 insertions(+) create mode 100644 benchmarks/FileIOSink/dart/FileIOSink.dart diff --git a/benchmarks/FileIOSink/dart/FileIOSink.dart b/benchmarks/FileIOSink/dart/FileIOSink.dart new file mode 100644 index 00000000000..85c0cc79efc --- /dev/null +++ b/benchmarks/FileIOSink/dart/FileIOSink.dart @@ -0,0 +1,114 @@ +// 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 setup() async { + _tempDir = Directory.systemTemp.createTempSync(); + _ioSink = File(_tempDir.uri.resolve('many-small').toFilePath()).openWrite(); + } + + @override + Future teardown() async { + await _ioSink.close(); + _tempDir.deleteSync(recursive: true); + } + + @override + Future 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 setup() async { + _tempDir = Directory.systemTemp.createTempSync(); + _ioSink = File(_tempDir.uri.resolve('one-large').toFilePath()).openWrite(); + } + + @override + Future teardown() async { + await _ioSink.close(); + _tempDir.deleteSync(recursive: true); + } + + @override + Future 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 setup() async { + _tempDir = Directory.systemTemp.createTempSync(); + _ioSink = File(_tempDir.uri.resolve('alternative-add-size').toFilePath()) + .openWrite(); + } + + @override + Future teardown() async { + await _ioSink.close(); + _tempDir.deleteSync(recursive: true); + } + + @override + Future run() async { + _ioSink.add(_largeData); + _ioSink.add(_smallData); + await _ioSink.flush(); + } +} + +void main() { + final benchmarks = [ + BenchmarkManySmallAdds(), + BenchmarkOneLargeAdd(), + BenchmarkAlternatingSizedAdd(), + ]; + + for (final benchmark in benchmarks) { + benchmark.report(); + } +}