Add profile stats to the CPU profiler (#5340)
diff --git a/packages/devtools_app/lib/src/screens/performance/panes/timeline_events/legacy/event_details.dart b/packages/devtools_app/lib/src/screens/performance/panes/timeline_events/legacy/event_details.dart index 9527c7e..936baf2 100644 --- a/packages/devtools_app/lib/src/screens/performance/panes/timeline_events/legacy/event_details.dart +++ b/packages/devtools_app/lib/src/screens/performance/panes/timeline_events/legacy/event_details.dart
@@ -14,6 +14,7 @@ import '../../../../profiler/cpu_profile_controller.dart'; import '../../../../profiler/cpu_profile_model.dart'; import '../../../../profiler/cpu_profiler.dart'; +import '../../../../profiler/panes/controls/profiler_controls.dart'; import '../../../performance_model.dart'; import '../../../performance_screen.dart'; import 'legacy_events_controller.dart';
diff --git a/packages/devtools_app/lib/src/screens/profiler/cpu_profiler.dart b/packages/devtools_app/lib/src/screens/profiler/cpu_profiler.dart index 094f34e..df074a0 100644 --- a/packages/devtools_app/lib/src/screens/profiler/cpu_profiler.dart +++ b/packages/devtools_app/lib/src/screens/profiler/cpu_profiler.dart
@@ -3,7 +3,6 @@ // found in the LICENSE file. import 'dart:async'; -import 'dart:developer'; import 'package:flutter/material.dart'; @@ -14,9 +13,9 @@ import '../../shared/feature_flags.dart'; import '../../shared/globals.dart'; import '../../shared/primitives/auto_dispose.dart'; +import '../../shared/primitives/utils.dart'; import '../../shared/theme.dart'; import '../../shared/ui/colors.dart'; -import '../../shared/ui/filter.dart'; import '../../shared/ui/search.dart'; import '../../shared/ui/tab.dart'; import '../../shared/utils.dart'; @@ -24,6 +23,7 @@ import 'cpu_profile_model.dart'; import 'panes/bottom_up.dart'; import 'panes/call_tree.dart'; +import 'panes/controls/profiler_controls.dart'; import 'panes/cpu_flame_chart.dart'; import 'panes/method_table/method_table.dart'; @@ -269,6 +269,8 @@ ); }, ), + if (currentTab.key != CpuProfiler.summaryTab) + CpuProfileStats(metadata: data.profileMetaData), ], ); } @@ -365,224 +367,65 @@ } } -class DisplayTreeGuidelinesToggle extends StatelessWidget { - const DisplayTreeGuidelinesToggle(); +// TODO(kenz): one improvement we could make on this is to show the denominator +// for filtered profiles (e.g. 'Sample count: 10/14), or to at least show the +// original value in the tooltip for each of these stats. +class CpuProfileStats extends StatelessWidget { + CpuProfileStats({required this.metadata}); + + final CpuProfileMetaData metadata; + + final _statsRowHeight = scaleByFontFactor(25.0); @override Widget build(BuildContext context) { - return ValueListenableBuilder<bool>( - valueListenable: preferences.cpuProfiler.displayTreeGuidelines, - builder: (context, displayTreeGuidelines, _) { - return ToggleButton( - onPressed: () { - preferences.cpuProfiler.displayTreeGuidelines.value = - !displayTreeGuidelines; - }, - isSelected: displayTreeGuidelines, - message: 'Display guidelines', - icon: Icons.stacked_bar_chart, - ); - }, - ); - } -} - -class CpuProfileFilterDialog extends StatelessWidget { - const CpuProfileFilterDialog({required this.controller, Key? key}) - : super(key: key); - - static const filterQueryInstructions = ''' -Type a filter query to show or hide specific stack frames. - -Any text that is not paired with an available filter key below will be queried against all categories (method, uri). - -Available filters: - 'uri', 'u' (e.g. 'uri:my_dart_package/some_lib.dart', '-u:some_lib_to_hide') - -Example queries: - 'someMethodName uri:my_dart_package,b_dart_package' - '.toString -uri:flutter' -'''; - - double get _filterDialogWidth => scaleByFontFactor(400.0); - - final CpuProfilerController controller; - - @override - Widget build(BuildContext context) { - return FilterDialog<CpuStackFrame>( - dialogWidth: _filterDialogWidth, - controller: controller, - queryInstructions: filterQueryInstructions, - ); - } -} - -class CpuProfilerDisabled extends StatelessWidget { - const CpuProfilerDisabled(this.controller); - - final CpuProfilerController controller; - - @override - Widget build(BuildContext context) { - return Center( - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: <Widget>[ - const Text('CPU profiler is disabled.'), - Padding( - padding: const EdgeInsets.all(8.0), - child: ElevatedButton( - onPressed: controller.enableCpuProfiler, - child: const Text('Enable profiler'), + final samplePeriodValid = metadata.samplePeriod > 0; + final samplingPeriodDisplay = samplePeriodValid + ? const Duration(seconds: 1).inMicroseconds ~/ metadata.samplePeriod + : '--'; + return OutlineDecoration( + child: Container( + height: _statsRowHeight, + padding: const EdgeInsets.all(densePadding), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + _stat( + tooltip: 'The duration of time spanned by the CPU samples', + text: 'Duration: ${msText(metadata.time!.duration)}', ), - ), - ], + _stat( + tooltip: 'The number of samples included in the profile', + text: 'Sample count: ${metadata.sampleCount}', + ), + _stat( + tooltip: + 'The frequency at which samples are collected by the profiler' + '${samplePeriodValid ? ' (once every ${metadata.samplePeriod} micros)' : ''}', + text: 'Sampling rate: $samplingPeriodDisplay Hz', + ), + _stat( + tooltip: 'The maximum stack trace depth of a collected sample', + text: 'Sampling depth: ${metadata.stackDepth}', + ), + ], + ), ), ); } -} -/// DropdownButton that controls the value of -/// [ProfilerScreenController.userTagFilter]. -class UserTagDropdown extends StatelessWidget { - const UserTagDropdown(this.controller); - - final CpuProfilerController controller; - - @override - Widget build(BuildContext context) { - const filterByTag = 'Filter by tag:'; - return ValueListenableBuilder<String>( - valueListenable: controller.userTagFilter, - builder: (context, userTag, _) { - final userTags = controller.userTags; - final tooltip = userTags.isNotEmpty - ? 'Filter the CPU profile by the given UserTag' - : 'No UserTags found for this CPU profile'; - return SizedBox( - height: defaultButtonHeight, - child: DevToolsTooltip( - message: tooltip, - child: ValueListenableBuilder<bool>( - valueListenable: preferences.vmDeveloperModeEnabled, - builder: (context, vmDeveloperModeEnabled, _) { - return RoundedDropDownButton<String>( - isDense: true, - style: Theme.of(context).textTheme.bodyMedium, - value: userTag, - items: [ - _buildMenuItem( - display: - '$filterByTag ${CpuProfilerController.userTagNone}', - value: CpuProfilerController.userTagNone, - ), - // We don't want to show the 'Default' tag if it is the only - // tag available. The 'none' tag above is equivalent in this - // case. - if (!(userTags.length == 1 && - userTags.first == UserTag.defaultTag.label)) ...[ - for (final tag in userTags) - _buildMenuItem( - display: '$filterByTag $tag', - value: tag, - ), - _buildMenuItem( - display: 'Group by: User Tag', - value: CpuProfilerController.groupByUserTag, - ), - ], - if (vmDeveloperModeEnabled) - _buildMenuItem( - display: 'Group by: VM Tag', - value: CpuProfilerController.groupByVmTag, - ), - ], - onChanged: userTags.isEmpty || - (userTags.length == 1 && - userTags.first == UserTag.defaultTag.label) - ? null - : (String? tag) => _onUserTagChanged(tag!), - ); - }, - ), - ), - ); - }, - ); - } - - DropdownMenuItem<String> _buildMenuItem({ - required String display, - required String value, + Widget _stat({ + required String text, + required String tooltip, }) { - return DropdownMenuItem<String>( - value: value, - child: Text(display), - ); - } - - void _onUserTagChanged(String newTag) async { - try { - await controller.loadDataWithTag(newTag); - } catch (e) { - notificationService.push(e.toString()); - } - } -} - -/// DropdownButton that controls the value of -/// [ProfilerScreenController.viewType]. -class ModeDropdown extends StatelessWidget { - const ModeDropdown(this.controller); - - final CpuProfilerController controller; - - @override - Widget build(BuildContext context) { - const mode = 'View:'; - return ValueListenableBuilder<CpuProfilerViewType>( - valueListenable: controller.viewType, - builder: (context, viewType, _) { - final tooltip = viewType == CpuProfilerViewType.function - ? 'Display the profile in terms of the Dart call stack ' - '(i.e., inlined frames are expanded)' - : 'Display the profile in terms of native stack frames ' - '(i.e., inlined frames are not expanded, display code objects ' - 'rather than individual functions)'; - return SizedBox( - height: defaultButtonHeight, - child: DevToolsTooltip( - message: tooltip, - child: RoundedDropDownButton<CpuProfilerViewType>( - isDense: true, - style: Theme.of(context).textTheme.bodyMedium, - value: viewType, - items: [ - _buildMenuItem( - display: '$mode ${CpuProfilerViewType.function}', - value: CpuProfilerViewType.function, - ), - _buildMenuItem( - display: '$mode ${CpuProfilerViewType.code}', - value: CpuProfilerViewType.code, - ), - ], - onChanged: (type) => controller.updateView(type!), - ), - ), - ); - }, - ); - } - - DropdownMenuItem<CpuProfilerViewType> _buildMenuItem({ - required String display, - required CpuProfilerViewType value, - }) { - return DropdownMenuItem<CpuProfilerViewType>( - value: value, - child: Text(display), + return Flexible( + child: DevToolsTooltip( + message: tooltip, + child: Text( + text, + overflow: TextOverflow.ellipsis, + ), + ), ); } }
diff --git a/packages/devtools_app/lib/src/screens/profiler/panes/controls/profiler_controls.dart b/packages/devtools_app/lib/src/screens/profiler/panes/controls/profiler_controls.dart new file mode 100644 index 0000000..9ccef12 --- /dev/null +++ b/packages/devtools_app/lib/src/screens/profiler/panes/controls/profiler_controls.dart
@@ -0,0 +1,241 @@ +// Copyright 2023 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'dart:developer'; + +import 'package:flutter/material.dart'; + +import '../../../../shared/common_widgets.dart'; +import '../../../../shared/globals.dart'; +import '../../../../shared/theme.dart'; +import '../../../../shared/ui/filter.dart'; +import '../../../../shared/utils.dart'; +import '../../cpu_profile_controller.dart'; +import '../../cpu_profile_model.dart'; +import '../../profiler_screen_controller.dart'; + +final profilerScreenSearchFieldKey = + GlobalKey(debugLabel: 'ProfilerScreenSearchFieldKey'); + +class DisplayTreeGuidelinesToggle extends StatelessWidget { + const DisplayTreeGuidelinesToggle(); + + @override + Widget build(BuildContext context) { + return ValueListenableBuilder<bool>( + valueListenable: preferences.cpuProfiler.displayTreeGuidelines, + builder: (context, displayTreeGuidelines, _) { + return ToggleButton( + onPressed: () { + preferences.cpuProfiler.displayTreeGuidelines.value = + !displayTreeGuidelines; + }, + isSelected: displayTreeGuidelines, + message: 'Display guidelines', + icon: Icons.stacked_bar_chart, + ); + }, + ); + } +} + +class CpuProfileFilterDialog extends StatelessWidget { + const CpuProfileFilterDialog({required this.controller, Key? key}) + : super(key: key); + + static const filterQueryInstructions = ''' +Type a filter query to show or hide specific stack frames. + +Any text that is not paired with an available filter key below will be queried against all categories (method, uri). + +Available filters: + 'uri', 'u' (e.g. 'uri:my_dart_package/some_lib.dart', '-u:some_lib_to_hide') + +Example queries: + 'someMethodName uri:my_dart_package,b_dart_package' + '.toString -uri:flutter' +'''; + + double get _filterDialogWidth => scaleByFontFactor(400.0); + + final CpuProfilerController controller; + + @override + Widget build(BuildContext context) { + return FilterDialog<CpuStackFrame>( + dialogWidth: _filterDialogWidth, + controller: controller, + queryInstructions: filterQueryInstructions, + ); + } +} + +class CpuProfilerDisabled extends StatelessWidget { + const CpuProfilerDisabled(this.controller); + + final CpuProfilerController controller; + + @override + Widget build(BuildContext context) { + return Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: <Widget>[ + const Text('CPU profiler is disabled.'), + Padding( + padding: const EdgeInsets.all(8.0), + child: ElevatedButton( + onPressed: controller.enableCpuProfiler, + child: const Text('Enable profiler'), + ), + ), + ], + ), + ); + } +} + +/// DropdownButton that controls the value of +/// [ProfilerScreenController.userTagFilter]. +class UserTagDropdown extends StatelessWidget { + const UserTagDropdown(this.controller); + + final CpuProfilerController controller; + + @override + Widget build(BuildContext context) { + const filterByTag = 'Filter by tag:'; + return ValueListenableBuilder<String>( + valueListenable: controller.userTagFilter, + builder: (context, userTag, _) { + final userTags = controller.userTags; + final tooltip = userTags.isNotEmpty + ? 'Filter the CPU profile by the given UserTag' + : 'No UserTags found for this CPU profile'; + return SizedBox( + height: defaultButtonHeight, + child: DevToolsTooltip( + message: tooltip, + child: ValueListenableBuilder<bool>( + valueListenable: preferences.vmDeveloperModeEnabled, + builder: (context, vmDeveloperModeEnabled, _) { + return RoundedDropDownButton<String>( + isDense: true, + style: Theme.of(context).textTheme.bodyMedium, + value: userTag, + items: [ + _buildMenuItem( + display: + '$filterByTag ${CpuProfilerController.userTagNone}', + value: CpuProfilerController.userTagNone, + ), + // We don't want to show the 'Default' tag if it is the only + // tag available. The 'none' tag above is equivalent in this + // case. + if (!(userTags.length == 1 && + userTags.first == UserTag.defaultTag.label)) ...[ + for (final tag in userTags) + _buildMenuItem( + display: '$filterByTag $tag', + value: tag, + ), + _buildMenuItem( + display: 'Group by: User Tag', + value: CpuProfilerController.groupByUserTag, + ), + ], + if (vmDeveloperModeEnabled) + _buildMenuItem( + display: 'Group by: VM Tag', + value: CpuProfilerController.groupByVmTag, + ), + ], + onChanged: userTags.isEmpty || + (userTags.length == 1 && + userTags.first == UserTag.defaultTag.label) + ? null + : (String? tag) => _onUserTagChanged(tag!), + ); + }, + ), + ), + ); + }, + ); + } + + DropdownMenuItem<String> _buildMenuItem({ + required String display, + required String value, + }) { + return DropdownMenuItem<String>( + value: value, + child: Text(display), + ); + } + + void _onUserTagChanged(String newTag) async { + try { + await controller.loadDataWithTag(newTag); + } catch (e) { + notificationService.push(e.toString()); + } + } +} + +/// DropdownButton that controls the value of +/// [ProfilerScreenController.viewType]. +class ModeDropdown extends StatelessWidget { + const ModeDropdown(this.controller); + + final CpuProfilerController controller; + + @override + Widget build(BuildContext context) { + const mode = 'View:'; + return ValueListenableBuilder<CpuProfilerViewType>( + valueListenable: controller.viewType, + builder: (context, viewType, _) { + final tooltip = viewType == CpuProfilerViewType.function + ? 'Display the profile in terms of the Dart call stack ' + '(i.e., inlined frames are expanded)' + : 'Display the profile in terms of native stack frames ' + '(i.e., inlined frames are not expanded, display code objects ' + 'rather than individual functions)'; + return SizedBox( + height: defaultButtonHeight, + child: DevToolsTooltip( + message: tooltip, + child: RoundedDropDownButton<CpuProfilerViewType>( + isDense: true, + style: Theme.of(context).textTheme.bodyMedium, + value: viewType, + items: [ + _buildMenuItem( + display: '$mode ${CpuProfilerViewType.function}', + value: CpuProfilerViewType.function, + ), + _buildMenuItem( + display: '$mode ${CpuProfilerViewType.code}', + value: CpuProfilerViewType.code, + ), + ], + onChanged: (type) => controller.updateView(type!), + ), + ), + ); + }, + ); + } + + DropdownMenuItem<CpuProfilerViewType> _buildMenuItem({ + required String display, + required CpuProfilerViewType value, + }) { + return DropdownMenuItem<CpuProfilerViewType>( + value: value, + child: Text(display), + ); + } +}
diff --git a/packages/devtools_app/lib/src/screens/profiler/profiler_screen.dart b/packages/devtools_app/lib/src/screens/profiler/profiler_screen.dart index aac6eb1..a109fc9 100644 --- a/packages/devtools_app/lib/src/screens/profiler/profiler_screen.dart +++ b/packages/devtools_app/lib/src/screens/profiler/profiler_screen.dart
@@ -24,14 +24,12 @@ import 'cpu_profile_controller.dart'; import 'cpu_profile_model.dart'; import 'cpu_profiler.dart'; +import 'panes/controls/profiler_controls.dart'; import 'profiler_screen_controller.dart'; final profilerScreenSearchFieldKey = GlobalKey(debugLabel: 'ProfilerScreenSearchFieldKey'); -const iosProfilerWorkaround = - 'https://github.com/flutter/flutter/issues/88466#issuecomment-905830680'; - class ProfilerScreen extends Screen { ProfilerScreen() : super.conditional(
diff --git a/packages/devtools_app/lib/src/screens/vm_developer/isolate_statistics/isolate_statistics_view.dart b/packages/devtools_app/lib/src/screens/vm_developer/isolate_statistics/isolate_statistics_view.dart index 7f5f3fa..072e5ad 100644 --- a/packages/devtools_app/lib/src/screens/vm_developer/isolate_statistics/isolate_statistics_view.dart +++ b/packages/devtools_app/lib/src/screens/vm_developer/isolate_statistics/isolate_statistics_view.dart
@@ -12,7 +12,7 @@ import '../../../shared/table/table.dart'; import '../../../shared/table/table_data.dart'; import '../../../shared/theme.dart'; -import '../../profiler/cpu_profiler.dart'; +import '../../profiler/panes/controls/profiler_controls.dart'; import '../vm_developer_common_widgets.dart'; import '../vm_developer_tools_screen.dart'; import '../vm_service_private_extensions.dart';
diff --git a/packages/devtools_app/release_notes/NEXT_RELEASE_NOTES.md b/packages/devtools_app/release_notes/NEXT_RELEASE_NOTES.md index d9b7ca8..2df6916 100644 --- a/packages/devtools_app/release_notes/NEXT_RELEASE_NOTES.md +++ b/packages/devtools_app/release_notes/NEXT_RELEASE_NOTES.md
@@ -15,7 +15,7 @@ TODO: Remove this section if there are not any general updates. ## CPU profiler updates -TODO: Remove this section if there are not any general updates. +* Add ability to inspect statistics for a CPU profile - [#5340](https://github.com/flutter/devtools/pull/5340) ## Memory updates TODO: Remove this section if there are not any general updates.
diff --git a/packages/devtools_app/test/cpu_profiler/cpu_profiler_test.dart b/packages/devtools_app/test/cpu_profiler/cpu_profiler_test.dart index ed8e607..7217928 100644 --- a/packages/devtools_app/test/cpu_profiler/cpu_profiler_test.dart +++ b/packages/devtools_app/test/cpu_profiler/cpu_profiler_test.dart
@@ -8,6 +8,7 @@ import 'package:devtools_app/src/screens/profiler/cpu_profiler.dart'; import 'package:devtools_app/src/screens/profiler/panes/bottom_up.dart'; import 'package:devtools_app/src/screens/profiler/panes/call_tree.dart'; +import 'package:devtools_app/src/screens/profiler/panes/controls/profiler_controls.dart'; import 'package:devtools_app/src/screens/profiler/panes/cpu_flame_chart.dart'; import 'package:devtools_app/src/screens/profiler/panes/method_table/method_table.dart'; import 'package:devtools_app/src/shared/charts/flame_chart.dart'; @@ -87,6 +88,7 @@ expect(find.byType(CpuCallTreeTable), findsNothing); expect(find.byType(CpuMethodTable), findsNothing); expect(find.byType(CpuProfileFlameChart), findsNothing); + expect(find.byType(CpuProfileStats), findsOneWidget); expect(find.byType(DisplayTreeGuidelinesToggle), findsOneWidget); expect(find.byType(UserTagDropdown), findsOneWidget); expect(find.byType(ExpandAllButton), findsOneWidget); @@ -120,6 +122,7 @@ expect(find.byType(CpuCallTreeTable), findsNothing); expect(find.byType(CpuMethodTable), findsNothing); expect(find.byType(CpuProfileFlameChart), findsNothing); + expect(find.byType(CpuProfileStats), findsNothing); expect(find.byType(DisplayTreeGuidelinesToggle), findsNothing); expect(find.byType(UserTagDropdown), findsNothing); expect(find.byType(ExpandAllButton), findsNothing); @@ -148,6 +151,7 @@ expect(find.byType(TabBar), findsOneWidget); expect(find.byKey(CpuProfiler.dataProcessingKey), findsNothing); expect(find.byType(CpuBottomUpTable), findsOneWidget); + expect(find.byType(CpuProfileStats), findsOneWidget); expect(find.byType(DisplayTreeGuidelinesToggle), findsOneWidget); expect(find.byType(UserTagDropdown), findsOneWidget); expect(find.byType(ExpandAllButton), findsOneWidget); @@ -177,8 +181,9 @@ expect(find.byType(TabBar), findsOneWidget); expect(find.byKey(CpuProfiler.dataProcessingKey), findsNothing); expect(find.byKey(summaryViewKey), findsOneWidget); - expect(find.byType(UserTagDropdown), findsNothing); + expect(find.byType(CpuProfileStats), findsNothing); expect(find.byType(DisplayTreeGuidelinesToggle), findsNothing); + expect(find.byType(UserTagDropdown), findsNothing); expect(find.byType(ExpandAllButton), findsNothing); expect(find.byType(CollapseAllButton), findsNothing); expect(find.byType(FlameChartHelpButton), findsNothing); @@ -780,4 +785,80 @@ }); }); }); + + group('$CpuProfileStats', () { + testWidgets('displays correctly', (WidgetTester tester) async { + final metadata = CpuProfileMetaData( + sampleCount: 100, + samplePeriod: 50, + stackDepth: 128, + time: TimeRange() + ..start = const Duration() + ..end = const Duration(seconds: 1), + ); + await tester.pumpWidget(wrap(CpuProfileStats(metadata: metadata))); + await tester.pumpAndSettle(); + + expect( + find.byTooltip('The duration of time spanned by the CPU samples'), + findsOneWidget, + ); + expect( + find.byTooltip('The number of samples included in the profile'), + findsOneWidget, + ); + expect( + find.byTooltip( + 'The frequency at which samples are collected by the profiler' + ' (once every 50 micros)', + ), + findsOneWidget, + ); + expect( + find.byTooltip('The maximum stack trace depth of a collected sample'), + findsOneWidget, + ); + expect(find.text('Duration: 1000.0 ms'), findsOneWidget); + expect(find.text('Sample count: 100'), findsOneWidget); + expect(find.text('Sampling rate: 20000 Hz'), findsOneWidget); + expect(find.text('Sampling depth: 128'), findsOneWidget); + }); + + testWidgets('displays correctly for invalid data', + (WidgetTester tester) async { + final metadata = CpuProfileMetaData( + sampleCount: 100, + samplePeriod: 0, + stackDepth: 128, + time: TimeRange() + ..start = const Duration() + ..end = const Duration(seconds: 1), + ); + await tester.pumpWidget(wrap(CpuProfileStats(metadata: metadata))); + await tester.pumpAndSettle(); + + expect( + find.byTooltip('The duration of time spanned by the CPU samples'), + findsOneWidget, + ); + expect( + find.byTooltip('The number of samples included in the profile'), + findsOneWidget, + ); + expect( + find.byTooltip( + 'The frequency at which samples are collected by the profiler', + ), + findsOneWidget, + ); + expect( + find.byTooltip('The maximum stack trace depth of a collected sample'), + findsOneWidget, + ); + expect(find.text('Duration: 1000.0 ms'), findsOneWidget); + expect(find.text('Sample count: 100'), findsOneWidget); + expect(find.text('Sampling rate: -- Hz'), findsOneWidget); + expect(find.text('Sampling depth: 128'), findsOneWidget); + }); + }); }
diff --git a/packages/devtools_app/test/cpu_profiler/profiler_screen_test.dart b/packages/devtools_app/test/cpu_profiler/profiler_screen_test.dart index bc468c6..48f30d3 100644 --- a/packages/devtools_app/test/cpu_profiler/profiler_screen_test.dart +++ b/packages/devtools_app/test/cpu_profiler/profiler_screen_test.dart
@@ -4,6 +4,7 @@ import 'package:devtools_app/devtools_app.dart'; import 'package:devtools_app/src/screens/profiler/cpu_profiler.dart'; +import 'package:devtools_app/src/screens/profiler/panes/controls/profiler_controls.dart'; import 'package:devtools_app/src/service/vm_flags.dart' as vm_flags; import 'package:devtools_app/src/shared/ui/vm_flag_widgets.dart'; import 'package:devtools_test/devtools_test.dart';
diff --git a/packages/devtools_app/test/performance/timeline_events/legacy/event_details_test.dart b/packages/devtools_app/test/performance/timeline_events/legacy/event_details_test.dart index ddef23d..fce2e73 100644 --- a/packages/devtools_app/test/performance/timeline_events/legacy/event_details_test.dart +++ b/packages/devtools_app/test/performance/timeline_events/legacy/event_details_test.dart
@@ -5,6 +5,7 @@ import 'package:devtools_app/devtools_app.dart'; import 'package:devtools_app/src/screens/performance/panes/timeline_events/legacy/event_details.dart'; import 'package:devtools_app/src/screens/profiler/cpu_profiler.dart'; +import 'package:devtools_app/src/screens/profiler/panes/controls/profiler_controls.dart'; import 'package:devtools_app/src/service/vm_flags.dart' as vm_flags; import 'package:devtools_app/src/shared/config_specific/import_export/import_export.dart'; import 'package:devtools_app/src/shared/ui/vm_flag_widgets.dart';
diff --git a/packages/devtools_app/test/test_infra/goldens/cpu_profiler_bottom_up_guidelines.png b/packages/devtools_app/test/test_infra/goldens/cpu_profiler_bottom_up_guidelines.png index ec278c8..c9c0f5a 100644 --- a/packages/devtools_app/test/test_infra/goldens/cpu_profiler_bottom_up_guidelines.png +++ b/packages/devtools_app/test/test_infra/goldens/cpu_profiler_bottom_up_guidelines.png Binary files differ
diff --git a/packages/devtools_app/test/test_infra/goldens/cpu_profiler_bottom_up_no_guidelines.png b/packages/devtools_app/test/test_infra/goldens/cpu_profiler_bottom_up_no_guidelines.png index 1a483fd..df7109f 100644 --- a/packages/devtools_app/test/test_infra/goldens/cpu_profiler_bottom_up_no_guidelines.png +++ b/packages/devtools_app/test/test_infra/goldens/cpu_profiler_bottom_up_no_guidelines.png Binary files differ
diff --git a/packages/devtools_app/test/test_infra/goldens/cpu_profiler_call_tree_guidelines.png b/packages/devtools_app/test/test_infra/goldens/cpu_profiler_call_tree_guidelines.png index cfc8b77..e01819b 100644 --- a/packages/devtools_app/test/test_infra/goldens/cpu_profiler_call_tree_guidelines.png +++ b/packages/devtools_app/test/test_infra/goldens/cpu_profiler_call_tree_guidelines.png Binary files differ
diff --git a/packages/devtools_app/test/test_infra/goldens/cpu_profiler_call_tree_no_guidelines.png b/packages/devtools_app/test/test_infra/goldens/cpu_profiler_call_tree_no_guidelines.png index 1828222..19b7ae0 100644 --- a/packages/devtools_app/test/test_infra/goldens/cpu_profiler_call_tree_no_guidelines.png +++ b/packages/devtools_app/test/test_infra/goldens/cpu_profiler_call_tree_no_guidelines.png Binary files differ