-
Notifications
You must be signed in to change notification settings - Fork 6k
Conversation
For some examples - on an iPhone 5, this would set the cache to roughly 48mb. On a Pixel 3, it would set it to about 111mb. On an iPhone X, about 131mb. All of these values are substantially lower than our current default of 512mb (a 4k display is still below it, a 5k is above that). We should watch this for performance regressions, but I suspect our current value is just too high. On a machine with the new Apple display, it would be about 977mb 😆 |
shell/common/shell.cc
Outdated
// Only set this if the user has _not_ requested a specific value. | ||
if (raster_cache_max_bytes_user_value_ == -1) { | ||
// This is the formula Android uses. | ||
int max_bytes = metrics.physical_width * metrics.physical_height * 12 * 4; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add shell unit tests for this? You can go over the 4K, 5K, and new mac display settings there :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will stop by - I'm struggling a bit on the test for this since things fizzle if there's no GrContext.
shell/common/shell.cc
Outdated
@@ -610,6 +611,18 @@ void Shell::OnPlatformViewSetViewportMetrics(const ViewportMetrics& metrics) { | |||
FML_DCHECK(is_setup_); | |||
FML_DCHECK(task_runners_.GetPlatformTaskRunner()->RunsTasksOnCurrentThread()); | |||
|
|||
// Only set this if the user has _not_ requested a specific value. | |||
if (raster_cache_max_bytes_user_value_ == -1) { | |||
// This is the formula Android uses. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we add a link to the Android formula? I'm curious how it gets the magic number 12.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added link to comment
shell/common/shell.cc
Outdated
@@ -859,9 +872,10 @@ void Shell::HandleEngineSkiaMessage(fml::RefPtr<PlatformMessage> message) { | |||
if (args == root.MemberEnd() || !args->value.IsInt()) | |||
return; | |||
|
|||
raster_cache_max_bytes_user_value_ = args->value.GetInt(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is running on the UI thread, but Shell::OnPlatformViewSetViewportMetrics
runs on the platform thread. Use a std::atomic
type for raster_cache_max_bytes_user_value_
.
Or perhaps a better way to go would be holding raster_cache_max_bytes_user_value_
in a std::optional
member within the rasterizer, which will only be accessed on the GPU thread. SetResourceCacheMaxBytes
can take a flag indicating whether it should set the raster_cache_max_bytes_user_value_
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please add a unit test for this in shell_unittests
. You can make the call to update the viewport metrics directly. Then you will have to post a task to the GPU thread to read the resource cache size for asserting.
shell/common/shell.h
Outdated
@@ -106,7 +106,10 @@ class Shell final : public PlatformView::Delegate, | |||
fml::WeakPtr<Engine> weak_engine_; // to be shared across threads | |||
fml::WeakPtr<Rasterizer> weak_rasterizer_; // to be shared across threads | |||
fml::WeakPtr<PlatformView> | |||
weak_platform_view_; // to be shared across threads | |||
weak_platform_view_; // to be shared across threads | |||
int raster_cache_max_bytes_user_value_; // The user-requested value for the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
std::optional<size_t> instead of magic values please.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Going to move this to rasterizer as a bool flag per @jason-simmons suggestion instead
shell/common/shell.cc
Outdated
// Only set this if the user has _not_ requested a specific value. | ||
if (raster_cache_max_bytes_user_value_ == -1) { | ||
// This is the formula Android uses. | ||
int max_bytes = metrics.physical_width * metrics.physical_height * 12 * 4; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How did we figure 12 times screen size was a good metric? Seems really large. But I am not sure what it should be. Maybe 3-4?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The android dev who pointed this out to me suggested that it should be lower (I think his suggestion was 5).
I think it's probably fine to make it lower, but this is what Android has.
Tests may have to wait for https://github.com/flutter/engine/pull/9486/files to land, which has some necessary reworking of GL testing harnesses to make testing this possible. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM. We are going to pair on images & caching tomorrow and author a GL based shell_unittest and add a test for this then.
@@ -101,6 +107,7 @@ class Rasterizer final : public SnapshotDelegate { | |||
std::unique_ptr<flutter::CompositorContext> compositor_context_; | |||
std::unique_ptr<flutter::LayerTree> last_layer_tree_; | |||
fml::closure next_frame_callback_; | |||
bool user_override_resource_cache_bytes_; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It may just be more future-proof to make this std::atomic<bool>
in case that someone mistakenly modified it on other threads (than the GPU thread) in a future PR. Considering the low frequency of reading/writing this bit, the overhead of that atomic bool should be negligible.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The rasterizer is only accessed on the GPU thread. I'd prefer not to imply that any part of the rasterizer is safe to access from other threads.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, this is in Rasterizer
, not Shell
. Ignore my earlier comment :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How about if I check that the method using it runs on the GPU thread?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't worry about it @dnfield . All fields of Rasterizer
are only safe inside the GPU thread. So there's little reason to just guard this single field by making your change more complex.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nevermind, I see what you're saying - just switched it to std::atomic
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Haha - Github did not refresh on me. Ok, reverted back.
This reverts commit 23230e3.
How is this change going to interact with the https://fuchsia.googlesource.com/topaz/+/1b6341661b0bcf57449bf648b1b4f83fbb83ac8e/runtime/flutter_runner/vulkan_surface_producer.cc#127 we do on Fuchsia? |
Hmm. This would end up overriding it. I was under the impression you were using the system channel that Jason implemented. If you send a system channel, we won't override it. |
Should we revert this in the mean time? It seems likely to me that this patch would end up increasing the cache size on Fuchsia. I can try to verify that. |
flutter/engine@8591bd3...f3761ba git log 8591bd3..f3761ba --no-merges --oneline f3761ba Roll fuchsia/sdk/core/mac-amd64 from pWygawI3vBzP9dYloEvKka8r1p0NpLLZzZQ-yMYI1UIC to ZZsO1TTl-976ngr5N8h6rRvXTbMO_3qyKDpbeOhE0dwC (flutter/engine#9510) a83fe3e Roll Fuchsia SDK to latest (flutter/engine#9509) 63c2c33 Improve caching limits for Skia (flutter/engine#9503) 8876f6e Revert Skia version to d8f79a27b06b5bce7a27f89ce2d43d39f8c058dc (flutter/engine#9507) The AutoRoll server is located here: https://autoroll.skia.org/r/flutter-engine-flutter-autoroll Documentation for the AutoRoller is here: https://skia.googlesource.com/buildbot/+/master/autoroll/README.md If the roll is causing failures, please contact the current sheriff ([email protected]), and stop the roller if necessary.
I'm not familiar with the "system channel that Jason implemented" thing? Can you provide a github/googlesource/codesearch link? We probably don't need to full on revert this change, but we should be mindful of the effect that is has on Fuchsia. |
Sorry for being vague there, I assumed you were the one it was implemented for (I think it was actually requested by someone else). Flutter provides a system channel to control this value. A Flutter app/mod, from Dart code, can tell the engine to use X number of bytes for the resource cache. This would override whatever was picked in the vulkan_surface_producer.cc anyway. The interface is here: https://github.com/flutter/flutter/blob/v1.5.4-hotfix.2/packages/flutter/lib/src/services/system_channels.dart#L232 That gets pumped through to the same SetResourceCacheMaxBytes call eventually, and can be called at any point in the mod's lifecycle. |
@@ -610,6 +610,16 @@ void Shell::OnPlatformViewSetViewportMetrics(const ViewportMetrics& metrics) { | |||
FML_DCHECK(is_setup_); | |||
FML_DCHECK(task_runners_.GetPlatformTaskRunner()->RunsTasksOnCurrentThread()); | |||
|
|||
// This is the formula Android uses. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Where is this method called from?
On android it looks like the engine method is called directly:
engine->SetViewportMetrics(metrics); |
iOS looks like it does the same:
engine->SetViewportMetrics(std::move(metrics)); |
I'm not seeing this code getting run unless I add platform_view_->SetViewportMetrics(metrics);
to
void AndroidShellHolder::SetViewportMetrics( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is called by the embedders when the tell the PlatformView to update the viewport metrics. On iOS, this happens in response to a few things in FlutterViewController's lifecycle, and is funnled through here: https://github.com/flutter/engine/blob/master/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm#L674
On Android, that call results from similar things in FlutterView.java which all funnel through https://github.com/flutter/engine/blob/master/shell/platform/android/io/flutter/view/FlutterView.java#L614.
Unless you're writing your own embedding, you should never call this method. The reason I put the change here is because this is the method where we learn about screen resolution changes, and we want the cache size to be based on a multiple of screen resolution.
It's possible to override that entirely by using the Skia
platform channel.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you go down the callstack from FlutterView.java you don't get here, you get to the engine call.
mNativeView.getFlutterJNI().setViewportMetrics(mMetrics.devicePixelRatio, mMetrics.physicalWidth, |
ANDROID_SHELL_HOLDER->SetViewportMetrics(metrics); |
engine->SetViewportMetrics(metrics); |
Before this change calling the engine SetViewportMetrics was equivalent to calling the platform view wrapper around it. Its not after this change.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ahh that's unexpected. The other similar methods in the JNI platform view just forward to platform view. I think it'd be reasonable to change this one to do the same.
Woudl that unstick you?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When I add that line the engine crashes in release mode because surface_ seems to be null here:
engine/shell/common/rasterizer.cc
Line 424 in 2284210
GrContext* context = surface_->GetContext(); |
I'm not sure why surface_ is null in release mode but not debug mode.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It depends on where you're calling this - the surface may not have been set up yet and perhaps there's some race condition...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I mentioned this on #9729, but since the effect of this change seems to have been to reduce the default cache size from 512mb to 24mb should it be rolled back?
flutter/engine@8591bd3...f3761ba git log 8591bd3..f3761ba --no-merges --oneline f3761ba Roll fuchsia/sdk/core/mac-amd64 from pWygawI3vBzP9dYloEvKka8r1p0NpLLZzZQ-yMYI1UIC to ZZsO1TTl-976ngr5N8h6rRvXTbMO_3qyKDpbeOhE0dwC (flutter/engine#9510) a83fe3e Roll Fuchsia SDK to latest (flutter/engine#9509) 63c2c33 Improve caching limits for Skia (flutter/engine#9503) 8876f6e Revert Skia version to d8f79a27b06b5bce7a27f89ce2d43d39f8c058dc (flutter/engine#9507) The AutoRoll server is located here: https://autoroll.skia.org/r/flutter-engine-flutter-autoroll Documentation for the AutoRoller is here: https://skia.googlesource.com/buildbot/+/master/autoroll/README.md If the roll is causing failures, please contact the current sheriff ([email protected]), and stop the roller if necessary.
Our current Skia cache limit for the on screen GrContext is 512mb. We already know this is too big for some lower end devices, and so we've implemented a custom channel to allow applications or embedders to easily set a lower value.
The value is just too high for lower end devices with little ram. Android P+ uses the formula added here - I've also set the initial value substantially lower so we don't end up allocating lots of memory while waiting for the screen metrics to get pumped through.
Fixes flutter/flutter#35091
Fixes flutter/flutter#35038
/cc @ened
/cc @nathanrogersgoogle