190 lines
5.7 KiB
Dart

// Author: Hugo Pointcheval
// Email: git@pcl.ovh
// -----
// File: benchmark_page.dart
// Created Date: 28/12/2021 15:12:39
// Last Modified: 26/05/2022 20:19:28
// -----
// Copyright (c) 2021
import 'dart:math';
import 'dart:typed_data';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:native_crypto/native_crypto.dart';
import 'package:native_crypto_example/pointycastle/aes_gcm.dart';
import 'package:native_crypto_example/widgets/button.dart';
import '../session.dart';
import '../widgets/output.dart';
class BenchmarkPage extends ConsumerWidget {
BenchmarkPage({Key? key}) : super(key: key);
final Output keyContent = Output();
final Output benchmarkStatus = Output(large: true);
Future<void> _benchmark(
WidgetRef ref,
Cipher cipher, {
bool usePc = false,
bool encryptionOnly = false,
}) async {
Session state = ref.read(sessionProvider.state).state;
AesGcm pc = AesGcm();
if (state.secretKey.bytes.isEmpty) {
benchmarkStatus
.print('No SecretKey!\nGo in Key tab and generate or derive one.');
return;
}
List<int> testedSizes = [2, 4, 8, 16, 32, 64, 128, 256];
int multiplier = pow(2, 20).toInt(); // MiB
benchmarkStatus.print("[Benchmark] Sizes: ${testedSizes.join('/')}MiB\n");
benchmarkStatus.appendln(
"[Benchmark] Engine: " + (usePc ? " PointyCastle" : " NativeCrypto"));
benchmarkStatus.appendln("[Benchmark] Test: " +
(encryptionOnly ? " Encryption Only" : " Encryption & Decryption"));
benchmarkStatus.appendln(
'[Benchmark] bytesCountPerChunk: ${Cipher.bytesCountPerChunk} bytes/chunk');
String csv = encryptionOnly
? "Run;Size (B);Encryption Time (ms)\n"
: "Run;Size (B);Encryption Time (ms);Decryption Time (ms)\n";
int run = 0;
var beforeBench = DateTime.now();
for (int size in testedSizes) {
run++;
final StringBuffer csvLine = StringBuffer();
final dummyBytes = Uint8List(size * multiplier);
csvLine.write('$run;${size * multiplier};');
// Encryption
Object encryptedBigFile;
var before = DateTime.now();
if (usePc) {
encryptedBigFile = pc.encrypt(dummyBytes, state.secretKey.bytes);
} else {
encryptedBigFile = await cipher.encrypt(dummyBytes);
}
var after = DateTime.now();
var benchmark =
after.millisecondsSinceEpoch - before.millisecondsSinceEpoch;
benchmarkStatus
.appendln('[Benchmark] ${size}MiB => Encryption took $benchmark ms');
csvLine.write('$benchmark');
if (!encryptionOnly) {
// Decryption
before = DateTime.now();
if (usePc) {
pc.decrypt(encryptedBigFile as Uint8List, state.secretKey.bytes);
} else {
await cipher.decrypt(encryptedBigFile as CipherTextWrapper);
}
after = DateTime.now();
benchmark =
after.millisecondsSinceEpoch - before.millisecondsSinceEpoch;
benchmarkStatus.appendln(
'[Benchmark] ${size}MiB => Decryption took $benchmark ms');
csvLine.write(';$benchmark');
}
csv += csvLine.toString() + '\n';
}
var afterBench = DateTime.now();
var benchmark =
afterBench.millisecondsSinceEpoch - beforeBench.millisecondsSinceEpoch;
var sum = testedSizes.reduce((a, b) => a + b);
benchmarkStatus
.appendln('[Benchmark] Finished: ${sum}MiB in $benchmark ms');
benchmarkStatus.appendln('[Benchmark] Check the console for csv data');
benchmarkStatus.appendln(csv);
debugPrint(csv);
}
void _clear() {
benchmarkStatus.clear();
}
@override
Widget build(BuildContext context, WidgetRef ref) {
Session state = ref.read(sessionProvider.state).state;
if (state.secretKey.bytes.isEmpty) {
keyContent
.print('No SecretKey!\nGo in Key tab and generate or derive one.');
return SingleChildScrollView(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
children: [
const Align(
child: Text("Secret Key"),
alignment: Alignment.centerLeft,
),
keyContent,
],
),
),
);
}
keyContent.print(state.secretKey.bytes.toString());
AES cipher = AES(state.secretKey);
return SingleChildScrollView(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
children: [
const Align(
child: Text("Secret Key"),
alignment: Alignment.centerLeft,
),
keyContent,
Wrap(
children: [
Button(
() => _benchmark(ref, cipher),
"NativeCrypto",
),
const SizedBox(width: 8),
Button(
() => _benchmark(ref, cipher, usePc: true),
"PointyCastle",
),
const SizedBox(width: 8),
Button(
() => _benchmark(ref, cipher, encryptionOnly: true),
"NC Encryption Only",
),
const SizedBox(width: 8),
Button(
() => _benchmark(
ref,
cipher,
usePc: true,
encryptionOnly: true,
),
"PC Encryption Only",
),
const SizedBox(width: 8),
Button(
_clear,
"Clear",
),
],
),
benchmarkStatus,
],
),
),
);
}
}