// Times the writer of capsules of datekeys-dart, stage 6b, on the VM and // compiled to JavaScript: a capsule of one small file with time_only, and // with time_and_key and a portable key, whose 16 slots add INNER_ACCESS_AGE; // and one file of 64 MiB on the VM and 16 MiB in Node.js, read in streaming // in pieces of 1 MiB, to a sink that drops what it receives. Each is the // median of a few runs. The random values come from the CSPRNG of the // platform, as in production. // // dart run tool/encrypt3_bench.dart // // dart compile js -O2 -o encrypt3_bench.js tool/encrypt3_bench.dart // node -e "globalThis.self = globalThis; require('./encrypt3_bench.js')" // // ignore_for_file: avoid_print import 'dart:typed_data'; import 'package:datekeys/datekeys.dart'; const isWeb = identical(0, 0.0); double median(List xs) => (xs..sort())[xs.length ~/ 2]; /// The median time of [f], in milliseconds, over [runs] runs. Future time(int runs, Future Function() f) async { final times = []; for (var i = 0; i < runs; i++) { final sw = Stopwatch()..start(); await f(); times.add(sw.elapsedMicroseconds / 1000); } return median(times); } /// A sink that counts what it receives. final class Counting implements ByteSink { int n = 0; @override void add(Uint8List bytes) => n += bytes.length; @override void close() {} @override void abort(Object reason) {} } EncryptOptions options({AccessPolicy policy = AccessPolicy.timeOnly}) { final p = quicknet(); return EncryptOptions( profile: p, unlockAt: roundTime(p, 1000), now: () => Instant(p.genesisTime), policy: policy, newPortableKey: policy == AccessPolicy.timeAndKey, ); } Future main() async { final small = [FileSource.bytes('nota.txt', 'Hola.\n'.codeUnits)]; final t1 = await time(9, () async { await encryptFiles(Counting(), small, options()); }); print('time_only, one small file: ${t1.toStringAsFixed(1)} ms'); final t2 = await time(9, () async { await encryptFiles( Counting(), small, options(policy: AccessPolicy.timeAndKey), ); }); print('time_and_key, a portable key: ${t2.toStringAsFixed(1)} ms'); final mib = isWeb ? 16 : 64; final piece = Uint8List(1 << 20); final big = FileSource( path: 'big.bin', size: mib << 20, open: () async* { for (var i = 0; i < mib; i++) { yield piece; } }, ); final sink = Counting(); final t3 = await time(3, () async { sink.n = 0; await encryptFiles(sink, [big], options()); }); print( '$mib MiB in streaming, read twice: ${(t3 / 1000).toStringAsFixed(2)} s, ' '${(mib / (t3 / 1000)).toStringAsFixed(0)} MiB/s, ' '${sink.n} bytes written', ); }