Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FontImageSource renders slow on Android in ImageButton and Image #22757

Closed
davidortinau opened this issue May 31, 2024 · 18 comments
Closed

FontImageSource renders slow on Android in ImageButton and Image #22757

davidortinau opened this issue May 31, 2024 · 18 comments
Assignees
Labels
area-image Image loading, sources, caching p/1 Work that is important, and has been scheduled for release in this or an upcoming sprint platform/android 🤖 potential-regression This issue described a possible regression on a currently supported version., verification pending s/triaged Issue has been reviewed s/try-latest-version Please try to reproduce the potential issue on the latest public version s/verified Verified / Reproducible Issue ready for Engineering Triage t/bug Something isn't working t/perf The issue affects performance (runtime speed, memory usage, startup time, etc.) (sub: perf)

Comments

@davidortinau
Copy link
Contributor

davidortinau commented May 31, 2024

Description

In debug I can see the images paint, initially very slowly and then the second time I navigate they still draw much slower for ImageButton and Image than for Label.

FontThings.zip

Android:

slow.iconfont.rendering.mov

iOS for comparison is fine.

Simulator.Screen.Recording.-.iPhone.15.Pro.-.2024-05-31.at.09.03.06.mp4

9.0.0-preview.4.10690

I tested a release build, and while the first draw is faster, going between pages still has the icons bouncing around as they measure and layout.

Steps to Reproduce

No response

Link to public reproduction project repository

No response

Version with bug

9.0.0-preview.3.10457

Is this a regression from previous behavior?

Yes, this used to work in .NET MAUI

Last version that worked well

8.0.40 SR5

Affected platforms

Android

Affected platform versions

No response

Did you find any workaround?

No response

Relevant log output

No response

@davidortinau davidortinau added the t/bug Something isn't working label May 31, 2024
Copy link
Contributor

Hi I'm an AI powered bot that finds similar issues based off the issue title.

Please view the issues below to see if they solve your problem, and if the issue describes your problem please consider closing this one and thumbs upping the other issue to help us prioritize it. Thank you!

Open similar issues:

Closed similar issues:

Note: You can give me feedback by thumbs upping or thumbs downing this comment.

@PureWeen PureWeen added the area-controls-image Image control label May 31, 2024
@PureWeen PureWeen added the i/regression This issue described a confirmed regression on a currently supported version label May 31, 2024
@PureWeen PureWeen added this to the 9.0-preview5 milestone May 31, 2024
@PureWeen PureWeen modified the milestones: 9.0-preview5, .NET 8 SR6 Jun 1, 2024
@kevinxufei kevinxufei added s/verified Verified / Reproducible Issue ready for Engineering Triage s/triaged Issue has been reviewed labels Jun 3, 2024
@kevinxufei
Copy link

kevinxufei commented Jun 3, 2024

Verified this issue with Visual Studio 17.11.0 Preview 1(9.0.0-preview.4.10690/9.0.0-preview.2.10293/8.0.40/8.0.21/8.0.3). Can repro on android platform with sample project.
This may not a regression.

@mattleibow
Copy link
Member

I cannot repro this on the latest 8.0.40 nor the latest nightly nor main.

If this is just net9, then maybe we need to test again after the main branch is merged.

@mattleibow
Copy link
Member

I managed to repro this on net9 using Preview 4 bits. I do get a bit different results, the initial load is like a few ms before the image appears, but then it is fast from then on.

@mattleibow
Copy link
Member

I see I am getting this now on my devbox...

So on my mac, all net8 versions seem to work. On the Windows devbox, all versions seem to be broken. The devbox seems to have acceleration issues - or that is what it said when I booted but I am not sure.

However, this all depends now before I start destroying my local machines. What type of machines are you using @davidortinau and @kevinxufei ? Physical machines? Remote desktops? Dev boxes? VMs?

@mattleibow
Copy link
Member

OK, looking at Windows machine, I see a very very small delay. My M1 mac has no delay, my Surface Laptop Studio is mostly good but there is like a 100-200ms delay, devbox is got a big flash.

I tested on my Samsung A53 and it seemed OK...

Maybe the emulators are making a small issue with the fact that the images are bing generated on the fly become more obvious. Not sure if ayone sees this on a real device or on a real machine - or is this in devoxes/VMs that might not have accelerated hardware?

@mattleibow mattleibow added t/perf The issue affects performance (runtime speed, memory usage, startup time, etc.) (sub: perf) potential-regression This issue described a possible regression on a currently supported version., verification pending and removed i/regression This issue described a confirmed regression on a currently supported version labels Jun 4, 2024
@mattleibow
Copy link
Member

mattleibow commented Jun 4, 2024

Testing some more on the slow devbox I found something interesting. I wrote this code:

// var imageSource = new FileImageSource
// {
// 	File = "dotnet_bot.png"
// };

var imageSource = new FontImageSource
{
	FontFamily = "FontAwesome",
	Color = Colors.Black,
	Glyph = IconFont.FootballBall
};

var sw = new Stopwatch();
sw.Start();

var mauiContext = Handler.MauiContext;
var provider = mauiContext.Services.GetService<IImageSourceServiceProvider>();
var service = provider.GetRequiredImageSourceService(imageSource);

#if ANDROID
var result = await service.GetDrawableAsync(imageSource, mauiContext.Context);
#endif

sw.Stop();

await DisplayAlert("TIME", sw.ElapsedMilliseconds.ToString(), "OK");

When using a FileImageSource, the first run is about 50-60ms and the subsequent are 0-1ms. However, when using a FontImageSource, the first run is a whopping 450-500ms and the next runs are better at 20-50ms.

FontImageSource seems to be much slower and on slower devices/emus it looks bad. However, this has been happening since GA (I have been testing with 8.0.3 and 8.0.41)

BUT... I do notice that 8.0.40 is about 100ms slower the inital run (about 550-600ms) and 50ms on subsequent runs (about 30-100ms). This also looks to just affect the FontImageSource as the FileImageSource seems unaffected.

@mattleibow mattleibow added area-image Image loading, sources, caching and removed area-controls-image Image control labels Jun 4, 2024
@mattleibow
Copy link
Member

I generated a speedscope of a Release build of 8.0.40 and there is very much a large set of interop happening. I wonder if something in the AOT profile change of we need to add it into the profile.

dotnet-dsrouter.exe_20240605_043053.speedscope.json

@mattleibow
Copy link
Member

mattleibow commented Jun 5, 2024

Tracking some timings (every day I run them I get totally new numbers):

8.0.40 (8.0.40+azdo.9568816)

Service Gen Total
11 289 300
12 345 357

8.0.21 (8.0.21+0-sha.44a1673f7d-azdo.9442930.44a1673f7d2da631396ec9820e1d5cf3c29c9b1a)

Service Gen Total
10 233 243
52 279 331
9 291 300

8.0.20 (8.0.20+0-sha.195c36c4a6-azdo.9385637.195c36c4a6e742f2c6393a002df2902ce3a508a4)

Service Gen Total
47 245 292
24 244 268

8.0.10 (8.0.10+0-sha.50a0144fa5-azdo.9223550.50a0144fa5d17bca177da784803efd971a54800f)

Service Gen Total
52 167 219

8.0.6 (8.0.6+1-sha.87f59a86d4-azdo.8922564.87f59a86d453c8bcf4f5db0fb21259083b0d2d76)

Service Gen Total
? ? ?

8.0.3 (8.0.3+2-sha.1ebb238ff3-azdo.8651303.1ebb238ff313b626fe40e33fb52bdf13697ede5c)

Service Gen Total
20 152 172
26 161 187

@mattleibow
Copy link
Member

mattleibow commented Jun 5, 2024

A better speedscope with a single load and nothing else:

8.0.40: dotnet-dsrouter.exe_20240605_223945.speedscope.json

8.0.3: dotnet-dsrouter.exe_20240605_225822.speedscope.json

@mattleibow
Copy link
Member

mattleibow commented Jun 5, 2024

I rebooted my emulator and now all the numbers are the same... So basically, not the proof anymore. Looks like the longer an emu runs the slower it becomes.

But if I look at the numbers, the do have a small different - 180ms to 300ms - which is about 100ms difference. This is most likely the AOT profile, but I will still try find some better answers.

However, testing 8.0.3 results in the same delay. I don't think this is a regression nor a new issue as a result of a slower load. Seems to just be slow devices. Somehow.

@PureWeen PureWeen modified the milestones: .NET 8 SR6, .NET 8 SR7 Jun 7, 2024
@PureWeen PureWeen modified the milestones: .NET 8 SR7, .NET 8 SR8 Jun 15, 2024
@PureWeen PureWeen modified the milestones: .NET 8 SR8, .NET 8 SR9 Jul 2, 2024
@samhouts samhouts removed s/verified Verified / Reproducible Issue ready for Engineering Triage s/triaged Issue has been reviewed labels Jul 3, 2024
@samhouts samhouts added s/verified Verified / Reproducible Issue ready for Engineering Triage s/triaged Issue has been reviewed labels Jul 10, 2024
@schinkenwuerfel
Copy link

schinkenwuerfel commented Jul 24, 2024

I just verified that the issue still is happening in 8.0.60.
However, I have found a workaround for this issue: We moslty use the FontImageSources in Buttons for showing icons instead of text. The workaround is to just use the glyphs passed into the FontImageSource as the Text of the Button instead of setting the FontImageSource as the ImageSource of the Button. For the few Images we use in our application a switch to a Label with the desired glyph as text is also possible.
This requires some refactoring of our code base tho which im not so keen on doing right now, so i wanted to check back if there are any further infos about this issue and if this is going to be fixed soon'ish?

@PureWeen PureWeen added the p/1 Work that is important, and has been scheduled for release in this or an upcoming sprint label Aug 2, 2024
@mattleibow
Copy link
Member

I think we found that there was no caching for the font images, so this PR will hopefully fix it a fair bit: #24021

@albyrock87
Copy link
Contributor

This is a benchmark from #24021

[Benchmark]
public async Task ImageHelperFromFont()
{
	var callback = new Callback();

	handler!.Post(() =>
	{
		Microsoft.Maui.PlatformInterop.LoadImageFromFont(
			context,
			Android.Graphics.Color.Aquamarine,
			"A",
			Typeface.Default,
			24,
			callback);
	});

	await callback.SuccessTask;
}

Before

Method Mean Error StdDev Gen0 Allocated
ImageHelperFromFont 408,206.3 ns 54,119.83 ns 153,528.95 ns 0.4883 2427 B

After

Method Mean Error StdDev Gen0 Allocated
ImageHelperFromFont 58,737.1 ns 1,222.72 ns 3,221.13 ns 0.4883 2327 B

@PureWeen PureWeen added the s/try-latest-version Please try to reproduce the potential issue on the latest public version label Aug 9, 2024
@gautambjain
Copy link

I took latest Visual Studio Version 17.10.5 and MAUI 8.0.80. I have a MAUI project that uses .Net 8.0.

The issue described above still exists. Please check the below link (few seconds video).

explorer_Z7qfzRQ340.mp4

I am using in xaml with FontImageSource. It draws the ListView once and after a second or so, shows the images.

How can I avoid/fix this? I cannot fix the grid row height as I want to make it compatible with different scaled display sizes (scaled text).

@albyrock87
Copy link
Contributor

albyrock87 commented Aug 12, 2024

@gautambjain I think this might be a different issue.
Have you tried to set a fixed size on the image/image button with the star icon?
Also may you share some code to look at?

@gautambjain
Copy link

Thanks @albyrock87 . I already had a fixed size of 28 on Image. The RowDefinition on the grid is set to Auto. So the row shows smaller and then larger as shown in video.

But I kind of fixed the row height by fixing the surrounding StackLayout MinimumHeightRequest to 28. Now the ListView rows show a bigger initial size but still the fonts appear little later. And there are more font icons I am using in the same list row (folder icon, alarm icon, contact icon) and I want them to show bigger when the user changes the default display/text size (scaled text and display).

But don't you think the actual issue of delayed FontImageSource loading still is shown in my video? What I did above is only a work around. But it will not work for all font icons and all scaled displays. It will still show a flicker like in the video.

@albyrock87
Copy link
Contributor

@gautambjain use adb and enable Glide-related logging as follows (before starting the app):

adb shell setprop log.tag.CustomViewTarget VERBOSE
adb shell setprop log.tag.GlideRequest VERBOSE    
adb shell setprop log.tag.Glide VERBOSE          
adb shell setprop log.tag.Engine VERBOSE 
adb shell setprop log.tag.HttpUrlFetcher VERBOSE 

Then start the app and reach you page and look at logs.

A sample load not from cache, see Started new load in 0.162708ms:

08-12 12:17:46.935 V/GlideRequest( 9801): Got onSizeReady in 0.024709 this: 47856178
08-12 12:17:46.936 V/GlideRequest( 9801): finished setup for calling load in 0.801292 this: 47856178
08-12 12:17:46.937 V/Engine  ( 9801): Started new load in 0.162708ms, key: EngineKey{model=com.microsoft.maui.glide.font.FontModel@756ffea1, width=-2147483648, height=-2147483648, resourceClass=class java.lang.Object, transcodeClass=class android.graphics.drawable.Drawable, signature=EmptySignature, hashCode=1275066720, transformations={}, options=Options{values={}}}
08-12 12:17:46.939 V/GlideRequest( 9801): finished onSizeReady in 3.9862919999999997 this: 47856178
08-12 12:17:46.939 V/GlideRequest( 9801): finished run method in 4.4395 this: 47856178

A sample load from cache, see Loaded resource from cache in 0.20099999999999998ms

08-12 12:17:50.390 V/GlideRequest( 9801): Got onSizeReady in 0.021374999999999998 this: 252343517
08-12 12:17:50.390 V/GlideRequest( 9801): finished setup for calling load in 0.6669579999999999 this: 252343517
08-12 12:17:50.391 V/Engine  ( 9801): Loaded resource from cache in 0.20099999999999998ms, key: EngineKey{model=com.microsoft.maui.glide.font.FontModel@756ffea1, width=-2147483648, height=-2147483648, resourceClass=class java.lang.Object, transcodeClass=class android.graphics.drawable.Drawable, signature=EmptySignature, hashCode=1275066720, transformations={}, options=Options{values={}}}
08-12 12:17:50.392 V/GlideRequest( 9801): finished onSizeReady in 2.222667 this: 252343517
08-12 12:17:50.393 V/GlideRequest( 9801): finished run method in 2.780042 this: 252343517

Now I would expect lots of them being loaded from cache.

Talking about MAUI internals, to load images we're using https://github.com/bumptech/glide library.
The nature of this library's image loading process is asynchronous which means there's always a chance to see (for example) a flicker while changing image source.
There's only one situation which appears to do a synchronous loading, which is when the image of the same size is in the memory cache (not disk cache).

In your case all images are appearing in the same moment for the first time, so maybe that means that none of them will find the image in cache.

I cannot understand what you're doing in the app from the video, but it seems you're suddenly displaying a collection view with some items.
Something like:

  1. Page shows a loading indicator
  2. Data has been loaded and set to a bound ItemsSource in a collection view

Now, on step 1, may you try to display all the icons somewhere in the page (with the same Size and Color you use inside the collection view)?

This should bring them into the memory cache and load should be immediate.

Let me know how it goes, and anyway, it'd be useful to have a simple how to reproduce code sample so we can include it into MAUI test cases and work on it.

@dotnet-policy-service dotnet-policy-service bot removed this from the .NET 8 SR9 milestone Aug 19, 2024
@github-project-automation github-project-automation bot moved this from Todo to Done in MAUI SDK Ongoing Aug 19, 2024
@github-actions github-actions bot locked and limited conversation to collaborators Oct 2, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area-image Image loading, sources, caching p/1 Work that is important, and has been scheduled for release in this or an upcoming sprint platform/android 🤖 potential-regression This issue described a possible regression on a currently supported version., verification pending s/triaged Issue has been reviewed s/try-latest-version Please try to reproduce the potential issue on the latest public version s/verified Verified / Reproducible Issue ready for Engineering Triage t/bug Something isn't working t/perf The issue affects performance (runtime speed, memory usage, startup time, etc.) (sub: perf)
Projects
Status: Done
Development

No branches or pull requests

8 participants