| // 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. |
| |
| import 'dart:async'; |
| import 'dart:isolate'; |
| import 'dart:typed_data'; |
| |
| import 'package:benchmark_harness/benchmark_harness.dart'; |
| |
| class SendReceiveBytes extends AsyncBenchmarkBase { |
| SendReceiveBytes(String name, |
| {required this.size, required this.useTransferable}) |
| : super(name); |
| |
| @override |
| Future<void> run() async { |
| await helper.run(); |
| } |
| |
| @override |
| Future<void> setup() async { |
| helper = SendReceiveHelper(size, useTransferable: useTransferable); |
| await helper.setup(); |
| } |
| |
| @override |
| Future<void> teardown() async { |
| await helper.finalize(); |
| } |
| |
| final bool useTransferable; |
| final int size; |
| late SendReceiveHelper helper; |
| } |
| |
| class StartMessage { |
| final SendPort sendPort; |
| final bool useTransferable; |
| final int size; |
| |
| StartMessage(this.sendPort, this.useTransferable, this.size); |
| } |
| |
| // Measures how long sending and receiving of [size]-length Uint8List takes. |
| class SendReceiveHelper { |
| SendReceiveHelper(this.size, {required this.useTransferable}); |
| |
| Future<void> setup() async { |
| data = Uint8List(size); |
| |
| port = ReceivePort(); |
| inbox = StreamIterator<dynamic>(port); |
| workerCompleted = Completer<bool>(); |
| workerExitedPort = ReceivePort() |
| ..listen((_) => workerCompleted.complete(true)); |
| worker = await Isolate.spawn( |
| isolate, StartMessage(port.sendPort, useTransferable, size), |
| onExit: workerExitedPort.sendPort); |
| await inbox.moveNext(); |
| outbox = inbox.current; |
| } |
| |
| Future<void> finalize() async { |
| outbox.send(null); |
| await workerCompleted.future; |
| workerExitedPort.close(); |
| port.close(); |
| } |
| |
| // Send data to worker, wait for an answer. |
| Future<void> run() async { |
| outbox.send(packageList(data, useTransferable)); |
| await inbox.moveNext(); |
| final received = inbox.current; |
| if (useTransferable) { |
| final TransferableTypedData transferable = received; |
| transferable.materialize(); |
| } |
| } |
| |
| late Uint8List data; |
| late ReceivePort port; |
| late StreamIterator<dynamic> inbox; |
| late SendPort outbox; |
| late Isolate worker; |
| late Completer<bool> workerCompleted; |
| late ReceivePort workerExitedPort; |
| final int size; |
| final bool useTransferable; |
| } |
| |
| Object packageList(Uint8List data, bool useTransferable) => |
| useTransferable ? TransferableTypedData.fromList(<Uint8List>[data]) : data; |
| |
| Future<void> isolate(StartMessage startMessage) async { |
| final port = ReceivePort(); |
| final inbox = StreamIterator<dynamic>(port); |
| final data = Uint8List.view(Uint8List(startMessage.size).buffer); |
| |
| startMessage.sendPort.send(port.sendPort); |
| while (true) { |
| await inbox.moveNext(); |
| final received = inbox.current; |
| if (received == null) { |
| break; |
| } |
| if (startMessage.useTransferable) { |
| final TransferableTypedData transferable = received; |
| transferable.materialize(); |
| } |
| startMessage.sendPort.send(packageList(data, startMessage.useTransferable)); |
| } |
| port.close(); |
| } |
| |
| class SizeName { |
| const SizeName(this.size, this.name); |
| |
| final int size; |
| final String name; |
| } |
| |
| const List<SizeName> sizes = <SizeName>[ |
| SizeName(1 * 1024, '1KB'), |
| SizeName(10 * 1024, '10KB'), |
| SizeName(100 * 1024, '100KB'), |
| SizeName(1 * 1024 * 1024, '1MB'), |
| SizeName(10 * 1024 * 1024, '10MB'), |
| SizeName(100 * 1024 * 1024, '100MB') |
| ]; |
| |
| Future<void> main() async { |
| for (final sizeName in sizes) { |
| await SendReceiveBytes('Isolate.SendReceiveBytes${sizeName.name}', |
| size: sizeName.size, useTransferable: false) |
| .report(); |
| await SendReceiveBytes( |
| 'Isolate.SendReceiveBytesTransferable${sizeName.name}', |
| size: sizeName.size, |
| useTransferable: true) |
| .report(); |
| } |
| } |