Created
March 24, 2025 19:09
-
-
Save HamdaanAliQuatil/c8846a43cae3a93184a76e8a915697ca to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import 'dart:isolate'; | |
import 'dart:async'; | |
import 'package:flutter/material.dart'; | |
import 'package:flutter/scheduler.dart'; | |
import 'package:webcrypto/webcrypto.dart'; | |
void main() { | |
runApp(const MyApp()); | |
} | |
class MyApp extends StatelessWidget { | |
const MyApp({super.key}); | |
@override | |
Widget build(BuildContext context) { | |
return const MaterialApp( | |
title: 'Isolate Performance Test', | |
debugShowCheckedModeBanner: false, | |
home: PerformanceTestPage(), | |
); | |
} | |
} | |
class PerformanceTestPage extends StatefulWidget { | |
const PerformanceTestPage({super.key}); | |
@override | |
_PerformanceTestPageState createState() => _PerformanceTestPageState(); | |
} | |
class _PerformanceTestPageState extends State<PerformanceTestPage> | |
with WidgetsBindingObserver, SingleTickerProviderStateMixin { | |
String _result = "Result: "; | |
bool _isRunning = false; | |
Timer? _timer; | |
Ticker? _ticker; | |
List<int> _frameDurations = []; | |
DateTime? _lastSampleTime; | |
@override | |
void initState() { | |
super.initState(); | |
WidgetsBinding.instance.addObserver(this); | |
WidgetsBinding.instance.addTimingsCallback(_onReportTimings); | |
_lastSampleTime = DateTime.now(); | |
_startFPSTimer(); | |
_ticker = createTicker((_) { | |
setState(() {}); | |
}); | |
_ticker?.start(); | |
} | |
@override | |
void dispose() { | |
_timer?.cancel(); | |
_ticker?.dispose(); | |
WidgetsBinding.instance.removeObserver(this); | |
WidgetsBinding.instance.removeTimingsCallback(_onReportTimings); | |
super.dispose(); | |
} | |
void _startFPSTimer() { | |
_timer = Timer.periodic(const Duration(seconds: 1), (timer) { | |
final now = DateTime.now(); | |
final elapsedMs = now.difference(_lastSampleTime!).inMilliseconds; | |
_lastSampleTime = now; | |
int frameCount = _frameDurations.length; | |
// Calculate FPS = (number of frames) * (1000 / elapsed milliseconds) | |
double fps = frameCount * 1000 / elapsedMs; | |
print("FPS: ${fps.toStringAsFixed(2)}; Frames: $frameCount; Elapsed: ${elapsedMs}ms"); | |
_frameDurations.clear(); | |
}); | |
} | |
void _onReportTimings(List<FrameTiming> timings) { | |
for (var timing in timings) { | |
// totalSpan is the total time (UI + Raster) for one frame. | |
int frameDuration = timing.totalSpan.inMilliseconds; | |
_frameDurations.add(frameDuration); | |
} | |
} | |
@override | |
void didHaveMemoryPressure() { | |
print("⚠️ Memory Pressure Detected!"); | |
} | |
@override | |
void didChangeMetrics() { | |
print("📏 Metrics Changed (Orientation or Resize Detected)"); | |
} | |
Future<void> _runOnMainThread() async { | |
setState(() { | |
_isRunning = true; | |
_result = "Running on Main Thread..."; | |
}); | |
Stopwatch stopwatch = Stopwatch()..start(); | |
int computationResult = await heavyComputation(100); | |
stopwatch.stop(); | |
setState(() { | |
_result = | |
"Main Thread:\nResult = $computationResult\nTime = ${stopwatch.elapsedMilliseconds} ms"; | |
_isRunning = false; | |
}); | |
} | |
Future<void> _runOnIsolate() async { | |
setState(() { | |
_isRunning = true; | |
_result = "Running on Isolate..."; | |
}); | |
Stopwatch stopwatch = Stopwatch()..start(); | |
int computationResult = await Isolate.run(() => heavyComputation(100)); | |
stopwatch.stop(); | |
setState(() { | |
_result = | |
"Isolate:\nResult = $computationResult\nTime = ${stopwatch.elapsedMilliseconds} ms"; | |
_isRunning = false; | |
}); | |
} | |
@override | |
Widget build(BuildContext context) { | |
return Scaffold( | |
appBar: AppBar( | |
title: const Text("Isolate Performance Test"), | |
), | |
body: Stack( | |
children: [ | |
SafeArea( | |
child: Padding( | |
padding: | |
const EdgeInsets.symmetric(horizontal: 20.0, vertical: 40.0), | |
child: Column( | |
crossAxisAlignment: CrossAxisAlignment.center, | |
children: [ | |
Expanded( | |
child: SingleChildScrollView( | |
child: Text( | |
_result, | |
style: const TextStyle(fontSize: 18), | |
textAlign: TextAlign.center, | |
), | |
), | |
), | |
const SizedBox(height: 20), | |
if (!_isRunning) | |
Column( | |
children: [ | |
ElevatedButton( | |
onPressed: _runOnMainThread, | |
child: const Text("Run on Main Thread"), | |
), | |
const SizedBox(height: 10), | |
ElevatedButton( | |
onPressed: _runOnIsolate, | |
child: const Text("Run on Isolate"), | |
), | |
], | |
), | |
if (_isRunning) const CircularProgressIndicator(), | |
const SizedBox(height: 30), | |
Text( | |
"Check console logs for FPS updates.", | |
style: TextStyle(fontSize: 16, color: Colors.grey[700]), | |
textAlign: TextAlign.center, | |
), | |
], | |
), | |
), | |
), | |
], | |
), | |
); | |
} | |
} | |
Future<int> heavyComputation(int n) async { | |
KeyPair<RsaOaepPrivateKey, RsaOaepPublicKey> keyPair; | |
for (int i = 0; i < n; i++) { | |
Stopwatch stopwatch = Stopwatch()..start(); | |
print("Generating RSA key pair..."); | |
const modulusLength = 2048; | |
final publicExponent = BigInt.from(65537); | |
const hash = Hash.sha256; | |
keyPair = await RsaOaepPrivateKey.generateKey( | |
modulusLength, publicExponent, hash); | |
stopwatch.stop(); | |
var elapsed = stopwatch.elapsedMilliseconds; | |
print("Time to generate RSA key pair: $elapsed ms"); | |
} | |
return 10; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment