Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions common/settings.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,12 @@ class FrameTiming {
return data_[phase] = value;
}

int64_t GetFrameKey() const { return frame_key_; }
void SetFrameKey(int64_t value) { frame_key_ = value; }

private:
fml::TimePoint data_[kCount];
int64_t frame_key_;
};

using TaskObserverAdd =
Expand Down
5 changes: 5 additions & 0 deletions flow/layers/layer_tree.h
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,10 @@ class LayerTree {
checkerboard_offscreen_layers_ = checkerboard;
}

void set_frame_key(int64_t frame_key) { frame_key_ = frame_key; }

int64_t frame_key() const { return frame_key_; }

private:
std::shared_ptr<Layer> root_layer_;
fml::TimePoint vsync_start_;
Expand All @@ -96,6 +100,7 @@ class LayerTree {
uint32_t rasterizer_tracing_threshold_;
bool checkerboard_raster_cache_images_;
bool checkerboard_offscreen_layers_;
int64_t frame_key_;

#ifdef FLUTTER_ENABLE_DIFF_CONTEXT
PaintRegionMap paint_region_map_;
Expand Down
9 changes: 6 additions & 3 deletions lib/ui/compositing.dart
Original file line number Diff line number Diff line change
Expand Up @@ -824,13 +824,16 @@ class SceneBuilder extends NativeFieldWrapperClass2 {
///
/// After calling this function, the scene builder object is invalid and
/// cannot be used further.
Scene build() {
///
/// A [frameKey] may be optionally supplied to associate any [FrameTiming]
/// objects and/or timeline traces with a particular identifier.
Scene build({int? frameKey}) {
final Scene scene = Scene._();
_build(scene);
_build(scene, frameKey ?? -1);
return scene;
}

void _build(Scene outScene) native 'SceneBuilder_build';
void _build(Scene outScene, int frameKey) native 'SceneBuilder_build';
}

/// (Fuchsia-only) Hosts content provided by another application.
Expand Down
9 changes: 6 additions & 3 deletions lib/ui/compositing/scene.cc
Original file line number Diff line number Diff line change
Expand Up @@ -31,17 +31,19 @@ void Scene::create(Dart_Handle scene_handle,
std::shared_ptr<flutter::Layer> rootLayer,
uint32_t rasterizerTracingThreshold,
bool checkerboardRasterCacheImages,
bool checkerboardOffscreenLayers) {
bool checkerboardOffscreenLayers,
int64_t frame_key) {
auto scene = fml::MakeRefCounted<Scene>(
std::move(rootLayer), rasterizerTracingThreshold,
checkerboardRasterCacheImages, checkerboardOffscreenLayers);
checkerboardRasterCacheImages, checkerboardOffscreenLayers, frame_key);
scene->AssociateWithDartWrapper(scene_handle);
}

Scene::Scene(std::shared_ptr<flutter::Layer> rootLayer,
uint32_t rasterizerTracingThreshold,
bool checkerboardRasterCacheImages,
bool checkerboardOffscreenLayers) {
bool checkerboardOffscreenLayers,
int64_t frame_key) {
// Currently only supports a single window.
auto viewport_metrics = UIDartState::Current()
->platform_configuration()
Expand All @@ -57,6 +59,7 @@ Scene::Scene(std::shared_ptr<flutter::Layer> rootLayer,
layer_tree_->set_checkerboard_raster_cache_images(
checkerboardRasterCacheImages);
layer_tree_->set_checkerboard_offscreen_layers(checkerboardOffscreenLayers);
layer_tree_->set_frame_key(frame_key);
}

Scene::~Scene() {}
Expand Down
6 changes: 4 additions & 2 deletions lib/ui/compositing/scene.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@ class Scene : public RefCountedDartWrappable<Scene> {
std::shared_ptr<flutter::Layer> rootLayer,
uint32_t rasterizerTracingThreshold,
bool checkerboardRasterCacheImages,
bool checkerboardOffscreenLayers);
bool checkerboardOffscreenLayers,
int64_t frame_key);

std::unique_ptr<flutter::LayerTree> takeLayerTree();

Expand All @@ -44,7 +45,8 @@ class Scene : public RefCountedDartWrappable<Scene> {
explicit Scene(std::shared_ptr<flutter::Layer> rootLayer,
uint32_t rasterizerTracingThreshold,
bool checkerboardRasterCacheImages,
bool checkerboardOffscreenLayers);
bool checkerboardOffscreenLayers,
int64_t frame_key);

std::unique_ptr<flutter::LayerTree> layer_tree_;
};
Expand Down
4 changes: 2 additions & 2 deletions lib/ui/compositing/scene_builder.cc
Original file line number Diff line number Diff line change
Expand Up @@ -344,12 +344,12 @@ void SceneBuilder::setCheckerboardOffscreenLayers(bool checkerboard) {
checkerboard_offscreen_layers_ = checkerboard;
}

void SceneBuilder::build(Dart_Handle scene_handle) {
void SceneBuilder::build(Dart_Handle scene_handle, int64_t frame_key) {
FML_DCHECK(layer_stack_.size() >= 1);

Scene::create(scene_handle, layer_stack_[0], rasterizer_tracing_threshold_,
checkerboard_raster_cache_images_,
checkerboard_offscreen_layers_);
checkerboard_offscreen_layers_, frame_key);
ClearDartWrapper(); // may delete this object.
}

Expand Down
2 changes: 1 addition & 1 deletion lib/ui/compositing/scene_builder.h
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ class SceneBuilder : public RefCountedDartWrappable<SceneBuilder> {
void setCheckerboardRasterCacheImages(bool checkerboard);
void setCheckerboardOffscreenLayers(bool checkerboard);

void build(Dart_Handle scene_handle);
void build(Dart_Handle scene_handle, int64_t frame_key);

static void RegisterNatives(tonic::DartLibraryNatives* natives);

Expand Down
20 changes: 14 additions & 6 deletions lib/ui/platform_dispatcher.dart
Original file line number Diff line number Diff line change
Expand Up @@ -433,10 +433,10 @@ class PlatformDispatcher {

// Called from the engine, via hooks.dart
void _reportTimings(List<int> timings) {
assert(timings.length % FramePhase.values.length == 0);
assert(timings.length % (FramePhase.values.length + 1) == 0);
final List<FrameTiming> frameTimings = <FrameTiming>[];
for (int i = 0; i < timings.length; i += FramePhase.values.length) {
frameTimings.add(FrameTiming._(timings.sublist(i, i + FramePhase.values.length)));
for (int i = 0; i < timings.length; i += FramePhase.values.length + 1) {
frameTimings.add(FrameTiming._(timings.sublist(i, i + FramePhase.values.length + 1)));
}
_invoke1(onReportTimings, _onReportTimingsZone, frameTimings);
}
Expand Down Expand Up @@ -1151,13 +1151,15 @@ class FrameTiming {
required int buildFinish,
required int rasterStart,
required int rasterFinish,
int? frameKey,
}) {
return FrameTiming._(<int>[
vsyncStart,
buildStart,
buildFinish,
rasterStart,
rasterFinish
rasterFinish,
frameKey ?? -1,
]);
}

Expand All @@ -1169,7 +1171,7 @@ class FrameTiming {
/// This constructor is usually only called by the Flutter engine, or a test.
/// To get the [FrameTiming] of your app, see [PlatformDispatcher.onReportTimings].
FrameTiming._(this._timestamps)
: assert(_timestamps.length == FramePhase.values.length);
: assert(_timestamps.length == FramePhase.values.length + 1);

/// This is a raw timestamp in microseconds from some epoch. The epoch in all
/// [FrameTiming] is the same, but it may not match [DateTime]'s epoch.
Expand Down Expand Up @@ -1214,13 +1216,19 @@ class FrameTiming {
/// See also [vsyncOverhead], [buildDuration] and [rasterDuration].
Duration get totalSpan => _rawDuration(FramePhase.rasterFinish) - _rawDuration(FramePhase.vsyncStart);

/// The frame key associated with this frame measurement, or `-1` if nothing
/// was provided.
///
/// This value should correspond the the frame key provided to [SceneBuilder.build].
int get frameKey => _timestamps.last;

final List<int> _timestamps; // in microseconds

String _formatMS(Duration duration) => '${duration.inMicroseconds * 0.001}ms';

@override
String toString() {
return '$runtimeType(buildDuration: ${_formatMS(buildDuration)}, rasterDuration: ${_formatMS(rasterDuration)}, vsyncOverhead: ${_formatMS(vsyncOverhead)}, totalSpan: ${_formatMS(totalSpan)})';
return '$runtimeType(buildDuration: ${_formatMS(buildDuration)}, rasterDuration: ${_formatMS(rasterDuration)}, vsyncOverhead: ${_formatMS(vsyncOverhead)}, totalSpan: ${_formatMS(totalSpan)}, frameKey: ${_timestamps.last})';
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ class LayerSceneBuilder implements ui.SceneBuilder {
}

@override
LayerScene build() {
LayerScene build({int? frameKey}) {
return LayerScene(rootLayer);
}

Expand Down
2 changes: 1 addition & 1 deletion lib/web_ui/lib/src/engine/html/scene_builder.dart
Original file line number Diff line number Diff line change
Expand Up @@ -538,7 +538,7 @@ class SurfaceSceneBuilder implements ui.SceneBuilder {
/// After calling this function, the scene builder object is invalid and
/// cannot be used further.
@override
SurfaceScene build() {
SurfaceScene build({int? frameKey}) {
// "Build finish" and "raster start" happen back-to-back because we
// render on the same thread, so there's no overhead from hopping to
// another thread.
Expand Down
2 changes: 1 addition & 1 deletion lib/web_ui/lib/src/ui/compositing.dart
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ abstract class SceneBuilder {
void setRasterizerTracingThreshold(int frameInterval);
void setCheckerboardRasterCacheImages(bool checkerboard);
void setCheckerboardOffscreenLayers(bool checkerboard);
Scene build();
Scene build({int? frameKey});
void setProperties(
double width,
double height,
Expand Down
1 change: 1 addition & 0 deletions shell/common/rasterizer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -349,6 +349,7 @@ RasterStatus Rasterizer::DoDraw(
timing.Set(FrameTiming::kBuildStart, layer_tree->build_start());
timing.Set(FrameTiming::kBuildFinish, layer_tree->build_finish());
timing.Set(FrameTiming::kRasterStart, fml::TimePoint::Now());
timing.SetFrameKey(layer_tree->frame_key());

PersistentCache* persistent_cache = PersistentCache::GetCacheForProcess();
persistent_cache->ResetStoredNewShaders();
Expand Down
5 changes: 3 additions & 2 deletions shell/common/shell.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1353,8 +1353,8 @@ void Shell::ReportTimings() {
size_t Shell::UnreportedFramesCount() const {
// Check that this is running on the raster thread to avoid race conditions.
FML_DCHECK(task_runners_.GetRasterTaskRunner()->RunsTasksOnCurrentThread());
FML_DCHECK(unreported_timings_.size() % FrameTiming::kCount == 0);
return unreported_timings_.size() / FrameTiming::kCount;
FML_DCHECK(unreported_timings_.size() % (FrameTiming::kCount + 1) == 0);
return unreported_timings_.size() / (FrameTiming::kCount + 1);
}

void Shell::OnFrameRasterized(const FrameTiming& timing) {
Expand All @@ -1375,6 +1375,7 @@ void Shell::OnFrameRasterized(const FrameTiming& timing) {
unreported_timings_.push_back(
timing.Get(phase).ToEpochDelta().ToMicroseconds());
}
unreported_timings_.push_back(timing.GetFrameKey());

// In tests using iPhone 6S with profile mode, sending a batch of 1 frame or a
// batch of 100 frames have roughly the same cost of less than 0.1ms. Sending
Expand Down