Skip to content

Instantly share code, notes, and snippets.

@HamdaanAliQuatil
Created March 24, 2025 19:09
Show Gist options
  • Save HamdaanAliQuatil/c8846a43cae3a93184a76e8a915697ca to your computer and use it in GitHub Desktop.
Save HamdaanAliQuatil/c8846a43cae3a93184a76e8a915697ca to your computer and use it in GitHub Desktop.
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