import 'package:flutter/material.dart';
class ProfileScope {
final String name;
final DateTime start;
final DateTime end;
const ProfileScope(this.name, this.start, this.end);
}
class ProfileFrame {
final int id;
final DateTime start;
final DateTime end;
final List<ProfileScope> scopes;
const ProfileFrame(this.id, this.start, this.end, this.scopes);
}
extension DurationExt on Duration {
double get toSeconds => this.inMicroseconds.toDouble() / 1000000.0;
}
class ProfilerPage extends StatelessWidget {
final List<ProfileFrame> frames;
const ProfilerPage(this.frames, {super.key});
@override
Widget build(BuildContext context) {
if (frames.isEmpty) {
return const Center(
child: Text(
"Run the project to see profiling information",
style: TextStyle(fontSize: 36),
),
);
}
final frameTimes = this.frames.map((frame) => frame.end.difference(frame.start)).toList();
final totalFrameTime = frameTimes.reduce((a, b) => a + b);
final averageFrameTime = totalFrameTime.inMicroseconds / this.frames.length;
final averageFps = this.frames.length / totalFrameTime.toSeconds;
Duration totalFrameTimeForPreviousSecond = const Duration();
final List<Duration> frameTimesForPreviousSecond = [];
for (int i = frameTimes.length - 1; i >= 0; i--) {
final currentFrameTime = frameTimes[i];
totalFrameTimeForPreviousSecond += currentFrameTime;
frameTimesForPreviousSecond.add(currentFrameTime);
if (totalFrameTimeForPreviousSecond.toSeconds >= 1.0) {
break;
}
}
frameTimesForPreviousSecond.sort((a, b) => b.compareTo(a));
final fpsLow = 1 /
frameTimesForPreviousSecond[(frameTimesForPreviousSecond.length / 20).floor()].toSeconds;
return Padding(
padding: const EdgeInsets.all(20),
child: Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text("Average Frame Time: ${averageFrameTime.round()} μs"),
Text("Average FPS: ${averageFps.round()} fps"),
Text("Low 5% FPS: ${fpsLow.round()}"),
],
),
],
),
);
}
}
|