You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
90 lines
3.1 KiB
90 lines
3.1 KiB
// Times the age writer of datekeys-dart, stage 6a, on the VM and compiled
|
|
// to JavaScript: the throughput of a large PAYLOAD_AGE encrypted in
|
|
// streaming, in pieces of 1 MiB, 64 MiB on the VM and 16 MiB in Node.js; and
|
|
// the header of each file of a capsule: PAYLOAD_AGE for one X25519
|
|
// recipient, INNER_ACCESS_AGE for 16 and a control of 103 bytes,
|
|
// OUTER_TIME_AGE for the tlock recipient, and the file of an author key, a
|
|
// scrypt recipient with logN 16. Each is the median of a few runs. The
|
|
// random values come from the CSPRNG of the platform, as in production.
|
|
//
|
|
// dart run tool/age_writer_bench.dart
|
|
//
|
|
// dart compile js -O2 -o age_writer_bench.js tool/age_writer_bench.dart
|
|
// node -e "globalThis.self = globalThis; require('./age_writer_bench.js')"
|
|
//
|
|
// ignore_for_file: avoid_print
|
|
import 'dart:typed_data';
|
|
|
|
import 'package:datekeys/datekeys.dart' show quicknet;
|
|
import 'package:datekeys/src/age_writer.dart';
|
|
import 'package:datekeys/src/random.dart';
|
|
import 'package:datekeys/src/recipient.dart';
|
|
|
|
const isWeb = identical(0, 0.0);
|
|
|
|
double median(List<double> xs) => (xs..sort())[xs.length ~/ 2];
|
|
|
|
/// The median time of [f], in milliseconds, over [runs] runs.
|
|
double time(int runs, void Function() f) {
|
|
final times = <double>[];
|
|
for (var i = 0; i < runs; i++) {
|
|
final sw = Stopwatch()..start();
|
|
f();
|
|
times.add(sw.elapsedMicroseconds / 1000);
|
|
}
|
|
return median(times);
|
|
}
|
|
|
|
void main() {
|
|
final id = generateX25519Identity();
|
|
final payload = X25519Recipient.of(id);
|
|
final slots = [
|
|
for (var i = 0; i < 16; i++) X25519Recipient.of(generateX25519Identity()),
|
|
];
|
|
final tlock = TimeRecipient(quicknet(), 1000);
|
|
final scrypt = ScryptRecipient('a passphrase', workFactor: 16);
|
|
final control = Uint8List(103);
|
|
|
|
print('age writer, ${isWeb ? 'Node.js' : 'VM'}');
|
|
print(
|
|
'PAYLOAD_AGE header, one X25519 stanza: '
|
|
'${time(15, () => AgeEncryptor([payload]).close()).toStringAsFixed(2)} ms',
|
|
);
|
|
print(
|
|
'INNER_ACCESS_AGE, 16 X25519 stanzas, 103 bytes: '
|
|
'${time(7, () => ageEncrypt(control, slots)).toStringAsFixed(1)} ms',
|
|
);
|
|
print(
|
|
'OUTER_TIME_AGE, the tlock stanza of round 1000, 2128 bytes: '
|
|
'${time(5, () => ageEncrypt(Uint8List(1773), [tlock])).toStringAsFixed(0)} ms',
|
|
);
|
|
print(
|
|
'an author key file, scrypt with logN 16: '
|
|
'${time(3, () => ageEncrypt(Uint8List(120), [scrypt])).toStringAsFixed(0)} ms',
|
|
);
|
|
|
|
// The throughput in streaming, in pieces of 1 MiB.
|
|
final mib = isWeb ? 16 : 64;
|
|
final piece = Uint8List(1 << 20);
|
|
for (var i = 0; i < piece.length; i++) {
|
|
piece[i] = (31 * i + 7) & 0xff;
|
|
}
|
|
final ms = time(3, () {
|
|
final e = AgeEncryptor([payload], random: secureRandom);
|
|
var n = e.header.length + e.nonce.length;
|
|
for (var i = 0; i < mib; i++) {
|
|
for (final c in e.add(piece)) {
|
|
n += c.length;
|
|
}
|
|
}
|
|
n += e.close().length;
|
|
if (n != ageFileLength([x25519StanzaLength], mib << 20)) {
|
|
throw StateError('$n bytes');
|
|
}
|
|
});
|
|
print(
|
|
'$mib MiB in streaming: ${(ms / 1000).toStringAsFixed(2)} s, '
|
|
'${(mib / ms * 1000).toStringAsFixed(1)} MiB/s',
|
|
);
|
|
}
|