mirror of
https://github.com/R0m1k3/xtremobile.git
synced 2026-10-11 17:29:26 +02:00
265 lines
7.2 KiB
Dart
265 lines
7.2 KiB
Dart
import 'dart:async';
|
|
import 'package:flutter/foundation.dart';
|
|
import 'package:hive/hive.dart';
|
|
|
|
/// Benchmark for Hive encryption performance impact
|
|
class HiveEncryptionBenchmark {
|
|
static final _results = <String, EncryptionBenchmarkResult>[];
|
|
|
|
/// Run encryption overhead benchmark
|
|
static Future<void> runBenchmark({
|
|
int writeCount = 1000,
|
|
int readCount = 1000,
|
|
String valueSize = 'medium', // small, medium, large
|
|
}) async {
|
|
if (kDebugMode) {
|
|
print('\n${'=' * 60}');
|
|
print('🔐 HIVE ENCRYPTION BENCHMARK');
|
|
print('=' * 60);
|
|
print('Write Operations: $writeCount');
|
|
print('Read Operations: $readCount');
|
|
print('Value Size: $valueSize');
|
|
print('=' * 60 + '\n');
|
|
}
|
|
|
|
// Generate test data
|
|
final testValue = _generateTestValue(valueSize);
|
|
|
|
try {
|
|
// Scenario 1: Unencrypted writes & reads
|
|
await _benchmarkUnencrypted(writeCount, readCount, testValue);
|
|
|
|
// Scenario 2: Encrypted writes & reads
|
|
await _benchmarkEncrypted(writeCount, readCount, testValue);
|
|
|
|
// Print comparison
|
|
_printComparison();
|
|
} catch (e) {
|
|
if (kDebugMode) {
|
|
print('❌ Benchmark error: $e');
|
|
}
|
|
}
|
|
}
|
|
|
|
static Future<void> _benchmarkUnencrypted(
|
|
int writes,
|
|
int reads,
|
|
String testValue,
|
|
) async {
|
|
const boxName = 'benchmark_unencrypted';
|
|
try {
|
|
// Clean up if exists
|
|
if (Hive.isBoxOpen(boxName)) {
|
|
await Hive.box(boxName).deleteFromDisk();
|
|
}
|
|
|
|
final box = await Hive.openBox<String>(boxName);
|
|
|
|
// Write benchmark
|
|
final writeStop = Stopwatch()..start();
|
|
for (int i = 0; i < writes; i++) {
|
|
await box.put('key_$i', testValue);
|
|
}
|
|
writeStop.stop();
|
|
|
|
// Read benchmark
|
|
final readStop = Stopwatch()..start();
|
|
for (int i = 0; i < reads; i++) {
|
|
box.get('key_${i % writes}');
|
|
}
|
|
readStop.stop();
|
|
|
|
// Delete benchmark
|
|
final deleteStop = Stopwatch()..start();
|
|
await box.deleteFromDisk();
|
|
deleteStop.stop();
|
|
|
|
final result = EncryptionBenchmarkResult(
|
|
name: 'Unencrypted (Hive)',
|
|
writeTimeMs: writeStop.elapsedMilliseconds,
|
|
readTimeMs: readStop.elapsedMilliseconds,
|
|
deleteTimeMs: deleteStop.elapsedMilliseconds,
|
|
operationCount: writes,
|
|
);
|
|
|
|
_results.add(result);
|
|
|
|
if (kDebugMode) {
|
|
print('\n📝 UNENCRYPTED RESULTS:');
|
|
result.print();
|
|
}
|
|
} catch (e) {
|
|
if (kDebugMode) {
|
|
print('❌ Unencrypted benchmark failed: $e');
|
|
}
|
|
}
|
|
}
|
|
|
|
static Future<void> _benchmarkEncrypted(
|
|
int writes,
|
|
int reads,
|
|
String testValue,
|
|
) async {
|
|
const boxName = 'benchmark_encrypted';
|
|
try {
|
|
// Clean up if exists
|
|
if (Hive.isBoxOpen(boxName)) {
|
|
await Hive.box(boxName).deleteFromDisk();
|
|
}
|
|
|
|
final encryptionKey = Hive.generateSecureKey();
|
|
|
|
final box = await Hive.openBox<String>(
|
|
boxName,
|
|
encryptionCipher: HiveAesCipher(encryptionKey),
|
|
);
|
|
|
|
// Write benchmark
|
|
final writeStop = Stopwatch()..start();
|
|
for (int i = 0; i < writes; i++) {
|
|
await box.put('key_$i', testValue);
|
|
}
|
|
writeStop.stop();
|
|
|
|
// Read benchmark
|
|
final readStop = Stopwatch()..start();
|
|
for (int i = 0; i < reads; i++) {
|
|
box.get('key_${i % writes}');
|
|
}
|
|
readStop.stop();
|
|
|
|
// Delete benchmark
|
|
final deleteStop = Stopwatch()..start();
|
|
await box.deleteFromDisk();
|
|
deleteStop.stop();
|
|
|
|
final result = EncryptionBenchmarkResult(
|
|
name: 'Encrypted (AES-256)',
|
|
writeTimeMs: writeStop.elapsedMilliseconds,
|
|
readTimeMs: readStop.elapsedMilliseconds,
|
|
deleteTimeMs: deleteStop.elapsedMilliseconds,
|
|
operationCount: writes,
|
|
);
|
|
|
|
_results.add(result);
|
|
|
|
if (kDebugMode) {
|
|
print('\n🔐 ENCRYPTED RESULTS:');
|
|
result.print();
|
|
}
|
|
} catch (e) {
|
|
if (kDebugMode) {
|
|
print('❌ Encrypted benchmark failed: $e');
|
|
}
|
|
}
|
|
}
|
|
|
|
static void _printComparison() {
|
|
if (_results.length >= 2) {
|
|
final unenc = _results[0];
|
|
final enc = _results[1];
|
|
|
|
final writeOverhead = ((enc.writeTimeMs / unenc.writeTimeMs - 1) * 100);
|
|
final readOverhead = ((enc.readTimeMs / unenc.readTimeMs - 1) * 100);
|
|
|
|
if (kDebugMode) {
|
|
print('\n${'=' * 60}');
|
|
print('📊 PERFORMANCE COMPARISON');
|
|
print('=' * 60);
|
|
print('\nWrite Performance:');
|
|
print(
|
|
' Unencrypted: ${unenc.writeTimeMs}ms (${(unenc.writeTimeMs / unenc.operationCount).toStringAsFixed(2)}µs/op)',
|
|
);
|
|
print(
|
|
' Encrypted: ${enc.writeTimeMs}ms (${(enc.writeTimeMs / enc.operationCount).toStringAsFixed(2)}µs/op)',
|
|
);
|
|
print(' Overhead: ${writeOverhead.toStringAsFixed(1)}%');
|
|
|
|
print('\nRead Performance:');
|
|
print(
|
|
' Unencrypted: ${unenc.readTimeMs}ms (${(unenc.readTimeMs / unenc.operationCount).toStringAsFixed(2)}µs/op)',
|
|
);
|
|
print(
|
|
' Encrypted: ${enc.readTimeMs}ms (${(enc.readTimeMs / enc.operationCount).toStringAsFixed(2)}µs/op)',
|
|
);
|
|
print(' Overhead: ${readOverhead.toStringAsFixed(1)}%');
|
|
|
|
// Status
|
|
const acceptableThreshold = 25.0;
|
|
final writeStatus = writeOverhead > acceptableThreshold ? '⚠️' : '✅';
|
|
final readStatus = readOverhead > acceptableThreshold ? '⚠️' : '✅';
|
|
|
|
print('\nStatus:');
|
|
print(
|
|
' $writeStatus Write overhead: ${writeOverhead.toStringAsFixed(1)}% (target: <$acceptableThreshold%)',
|
|
);
|
|
print(
|
|
' $readStatus Read overhead: ${readOverhead.toStringAsFixed(1)}% (target: <$acceptableThreshold%)',
|
|
);
|
|
print('=' * 60 + '\n');
|
|
}
|
|
}
|
|
}
|
|
|
|
static String _generateTestValue(String size) {
|
|
final base = 'test_value_' * 10;
|
|
switch (size) {
|
|
case 'small':
|
|
return base;
|
|
case 'large':
|
|
return base * 100;
|
|
default:
|
|
return base * 10;
|
|
}
|
|
}
|
|
|
|
static List<Map<String, dynamic>> toJson() {
|
|
return _results.map((r) => r.toJson()).toList();
|
|
}
|
|
|
|
static void reset() {
|
|
_results.clear();
|
|
}
|
|
}
|
|
|
|
/// Result of a single benchmark run
|
|
class EncryptionBenchmarkResult {
|
|
final String name;
|
|
final int writeTimeMs;
|
|
final int readTimeMs;
|
|
final int deleteTimeMs;
|
|
final int operationCount;
|
|
|
|
EncryptionBenchmarkResult({
|
|
required this.name,
|
|
required this.writeTimeMs,
|
|
required this.readTimeMs,
|
|
required this.deleteTimeMs,
|
|
required this.operationCount,
|
|
});
|
|
|
|
double get writePerOpUs => (writeTimeMs * 1000.0) / operationCount;
|
|
double get readPerOpUs => (readTimeMs * 1000.0) / operationCount;
|
|
|
|
void print() {
|
|
print(' Name: $name');
|
|
print(
|
|
' Write: ${writeTimeMs}ms (${writePerOpUs.toStringAsFixed(2)}µs/op)',
|
|
);
|
|
print(' Read: ${readTimeMs}ms (${readPerOpUs.toStringAsFixed(2)}µs/op)');
|
|
print(' Delete: ${deleteTimeMs}ms');
|
|
}
|
|
|
|
Map<String, dynamic> toJson() {
|
|
return {
|
|
'name': name,
|
|
'writeTimeMs': writeTimeMs,
|
|
'readTimeMs': readTimeMs,
|
|
'deleteTimeMs': deleteTimeMs,
|
|
'operationCount': operationCount,
|
|
'writePerOpUs': writePerOpUs,
|
|
'readPerOpUs': readPerOpUs,
|
|
};
|
|
}
|
|
}
|