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

TALRectangle, How optimize load Resource file ? #368

Open
maurobotta opened this issue Dec 9, 2024 · 42 comments
Open

TALRectangle, How optimize load Resource file ? #368

maurobotta opened this issue Dec 9, 2024 · 42 comments

Comments

@maurobotta
Copy link

maurobotta commented Dec 9, 2024

Hi @Zeus64

Attach project:
acrylicscroll-sample-ALCINOE.zip

I'm testing the performance of Alcinoe project.

Thank you for your great project! :)

My Steps:

  1. Download https://github.com/skia4delphi/acrylicscroll-sample

  2. Test and Android device, on Samsung S24 Ultra the scroll is .. medium

  3. i have converted the project at ALCINOE

  4. Re Test on Android device

  5. The image files .png are load in Resource mode, but the scroll is very slow for the first 5 seconds of scroll.

Is possibile opimize load of Resource PNG on TALRectangle ( TTask ? ) ?

Mauro Botta

Delphi 12.2
Last version of Alcinoe, Last version of Skia

@Zeus64
Copy link
Collaborator

Zeus64 commented Dec 9, 2024

What you're experiencing is normal. When you set TALRectangle to load its Fill property from a large PNG file (around 1 MB), it results in a slow process due to bilinear interpolation—this is common in any software handling large images.

To improve performance, you can force the form to create all its buffered bitmaps before the user starts scrolling. You can achieve this by using ALMakeBufDrawables(FakeContent). Take a look at the ALFmxControlsDemo in Alcinoe; I implemented the same solution there.

@maurobotta
Copy link
Author

maurobotta commented Dec 10, 2024

ALMakeBufDrawables(FakeContent), work fine :)

is "ALMakeBufDrawables" Thread safety ?

i have make any test..

Why Mode-2 with 10 split is more slow of Mode-1 ?


MODE 1 ALL IN ONE: 2.37 sec

Setlength(tasks_multi, 1);

tasks_multi[0] := TTask.Create (procedure ()
begin
TThread.Synchronize(nil,
procedure
begin
ALMakeBufDrawables(FakeContent);
// FakeContent is parent of Rectangle_Photo_1,Rectangle_Photo_2....
end);
end).Start;

while not TTask.WaitForAll(tasks_multi, 100) do
begin
CheckSynchronize(0);
Application.ProcessMessages;
end;


MODE 2 SPLIT 10 TASK : 2.38 sec

Setlength(tasks_multi, 10);

tasks_multi[0] := TTask.Create (procedure ()
begin
TThread.Synchronize(nil,
procedure
begin
ALMakeBufDrawables(Rectangle_Photo_1);
end);
end).Start;

tasks_multi[1] := TTask.Create (procedure ()
begin
TThread.Synchronize(nil,
procedure
begin
ALMakeBufDrawables(Rectangle_Photo_2);
end);
end).Start;

....
.....

while not TTask.WaitForAll(tasks_multi, 100) do
begin
CheckSynchronize(0);
Application.ProcessMessages;
end;

@Zeus64
Copy link
Collaborator

Zeus64 commented Dec 10, 2024

their is absolutely no advantage to do what you do, you create background thread and inside the background thread you do TThread.Synchronize that will ask the main thread to do the task! it's better to stay in the main thread and forget about TTask. also ALMakeBufDrawables is designed to work only in the main thread.

@maurobotta
Copy link
Author

maurobotta commented Dec 10, 2024

Bench Update

1 TThread.CreateAnonymousThread : 2.2 sec
10 tasks_multi_th[0] := TThread.CreateAnonymousThread : 0.6 sec

1 tasks_multi[0] := TTask.Created : 2.4 sec
10 tasks_multi[0] := TTask.Created : 2.5 sec

Array of Thread is VERY FAST.

Array of Thread without .WAIT is near 0.1 sec ( i can open App Without LAG scroll, now )

Delphi 12.2
Android 64 bit Samsung S24 Ulttra

last test:
compiled App in release , add LoadFunctionImage on Form SHOW, and i have a "Hyper Fast scroll".
Zero second ( before was 5 seconds ) of scroll lags.

@Zeus64
Copy link
Collaborator

Zeus64 commented Dec 10, 2024

you do badly, so call ALMakeBufDrawables from the main thread like in the alfmxcontrols sample. their is absolutely no gain to do like you do

@maurobotta
Copy link
Author

The problem might be in the management of TTasks in Delphi.

@Zeus64
Copy link
Collaborator

Zeus64 commented Dec 10, 2024

their is no problem, you simply create a background task and from the background task you ask to execute the code in the main thread = absolutely 0 advantage, it's even more slow

@Zeus64
Copy link
Collaborator

Zeus64 commented Jan 6, 2025

Hello, you can now try to use the last version of TALImage. in resourcename you can put an url and so the TALimage will download the image in the background and process it also in the background

@Zeus64 Zeus64 closed this as completed Jan 6, 2025
@maurobotta
Copy link
Author

Hi @Zeus64

I'm testing last version of ALCI , i have open ALFmxControls example compiled for Android 64 and iPhone 64, but the image is not visible.

https://.............landscape.jpg?raw=true

i debugging mode -- No error visilble.

All ok on Windows 64 ( landscape.jpg Image is visible) .

I have try my example with TALImage with a my link and don't work on Android and iphone.

Delphi 12.2

@Zeus64
Copy link
Collaborator

Zeus64 commented Jan 8, 2025

what you have in place of the image? can you show me a screenshot ? is it the same with this app : https://play.google.com/store/apps/details?id=io.magicfoundation.alcinoe.alfmxcontrolsdemo

@maurobotta
Copy link
Author

i have removed my APK, and i have installed from Google Store your deploy,.

Immagine WhatsApp 2025-01-08 ore 14 13 24_19150756

Immagine WhatsApp 2025-01-08 ore 14 13 24_a969650b

Immagine WhatsApp 2025-01-08 ore 14 13 24_c5d0f16d

Image landscape.jpg NOT visible.

---Samsung S24 Ultra

@maurobotta
Copy link
Author

is possible add this (great) feature to TALRectangle ?

@Zeus64
Copy link
Collaborator

Zeus64 commented Jan 8, 2025

something wrong somewhere :( normally when the image is downloading you must have a gray background and if the downloading failed you must have an error icon :( their is nothing in the android log ?

@Zeus64
Copy link
Collaborator

Zeus64 commented Jan 8, 2025

look like something in your network replace the downloaded file https://github.com/MagicFoundation/Alcinoe/blob/master/Demos/ALFmxControls/_Design/landscape.jpg?raw=true with an empty blank image :(

@maurobotta
Copy link
Author

my img .jpg on Amazon S3 don't work

@maurobotta
Copy link
Author

maurobotta commented Jan 8, 2025

i'm debugging...

ALLog() no warning

@Zeus64
Copy link
Collaborator

Zeus64 commented Jan 8, 2025

can you try again with the very last version i just commited ? and sent me the screenshoot ?

@maurobotta
Copy link
Author

get update.

{*************}
//[MultiThread]
class procedure TALImage.HandleResourceDownloadSuccess(const AResponse: IHTTPResponse; var AContentStream: TMemoryStream; var AExtData: TObject);
begin

DEBUG ENTER HERE !!!!!!!!

var LResourceDownloadExtData := TALImage.TResourceDownloadExtData(AExtData);
if LResourceDownloadExtData.owner = nil then exit;
LResourceDownloadExtData.ResourceStream := AContentStream;

@maurobotta
Copy link
Author

maurobotta commented Jan 8, 2025

class procedure TALImage.HandleResourceDownloadError(const AErrMessage: string; var AExtData: Tobject);
var

IS NEVER CALLED.

Your fix don't work.

@maurobotta
Copy link
Author

class procedure TALImage.HandleResourceDownloadSuccess(const AResponse: IHTTPResponse; var AContentStream: TMemoryStream; var AExtData: TObject);
var
...
LResourceDownloadExtData.ResourceStream := AContentStream;

iDebugSize := AContentStream.size;

HERE SIZE DOWNLOAD FILE IS CORRECT.

@maurobotta
Copy link
Author

maurobotta commented Jan 8, 2025

  • On my Samsung Tablet 2024 TAB A9+ work fine ( all versions ). Landscape.jpg is VISIBILE.

  • Samsung S24 Ultra NOT VISIBLE.

  • iPhone 11 PRO Max NOT VISIBLE.

@Zeus64
Copy link
Collaborator

Zeus64 commented Jan 8, 2025

On all my android device it's work good. On iphone i found the problem and just corrected it

@Zeus64
Copy link
Collaborator

Zeus64 commented Jan 8, 2025

just commited a fix for iOS, can you try it again ?

@Zeus64
Copy link
Collaborator

Zeus64 commented Jan 8, 2025

regarding android i try a several different phone, every work fine.
If the image is downloading then their is a gray background
If their is a problem downloading the image or decoding it then their is instead of the image a "broken image"

@maurobotta
Copy link
Author

maurobotta commented Jan 8, 2025

Get only: Alcinoe.FMX.Graphics.pas

on iPhone WORK FINE, now !!

on my phone Samsung S24 Don't work.

After TALImage.HandleResourceDownloadSuccess() You save the file on phone disk ?

@maurobotta
Copy link
Author

maurobotta commented Jan 8, 2025

--- If the image is downloading then their is a gray background

On S24 phone any time for 0.3 seconds a see a gray box, then make white clear.

@Zeus64
Copy link
Collaborator

Zeus64 commented Jan 8, 2025

so something wrong on your phone, because you have only 3 options :

  1. gray : downloading
  2. broken image: something goes wrong either in downloading or building the image
  3. the image: everything fine

can you try to run the app without Internet to see if you see the little broken image ?

@maurobotta
Copy link
Author

-- an you try to run the app without Internet to see if you see the little broken image ?

i have installed from Google Store your apk. Turn Off WIFI and Data , open .... no gray , no broken image, only ALL WHITE zone ( landscape.jpg )

i have open in Debug your project ALFmxControls on Android, without internet, there are any GPF / Error.

White like this:
image

@Zeus64
Copy link
Collaborator

Zeus64 commented Jan 9, 2025

It's really strange—it seems like your phone either downloaded an empty version of the image or is unable to render it. Could you try the following steps:

  1. Copy (Alcinoe)\Demos\ALFmxControls\_Design\landscape.jpg to (Alcinoe)\Demos\ALFmxControls\_Source\Resources\.

  2. Edit (Alcinoe)\Demos\ALFmxControls\_Source\Resources\Resources.rc and add the following line:
    landscape RCDATA "landscape.jpg"

  3. In the (Alcinoe)\Demos\ALFmxControls main form, add a new image and set its ResourceName property to landscape.

Let me know if you can see the image now.

@maurobotta
Copy link
Author

----Let me know if you can see the image now.

Yes, work fine. now.

( but is load in old local mode, no download file from web )

@Zeus64
Copy link
Collaborator

Zeus64 commented Jan 9, 2025

That proves the problem is with your internet. :( Something on your S24 phone is replacing the downloaded image stream with an empty one.

In TALImage.HandleResourceDownloadSuccess(), could you try replacing it with this version:

class procedure TALImage.HandleResourceDownloadSuccess(const AResponse: IHTTPResponse; var AContentStream: TMemoryStream; var AExtData: TObject);
begin
  var LResourceDownloadExtData := TALImage.TResourceDownloadExtData(AExtData);
  if LResourceDownloadExtData.owner = nil then exit;
  
  //LResourceDownloadExtData.ResourceStream := AContentStream;
  LResourceDownloadExtData.ResourceStream := TResourceStream.Create(HInstance, 'landscape', RT_RCDATA);
  
  TALGraphicThreadPool.Instance.ExecuteProc(
    CreateBufDrawable, // const AProc: TALWorkerThreadProc;
    LResourceDownloadExtData, // const AExtData: Tobject; TALGraphicThreadPool.Instance will own and release the ExtData object
    GetResourceDownloadPriority); // const APriority: Int64 = 0;
  AContentStream := nil; // AContentStream Will be free by AExtData
  AExtData := nil; // AExtData will be free by TALGraphicThreadPool.Instance
end;

@maurobotta
Copy link
Author

maurobotta commented Jan 9, 2025

As I wrote above, inside "HandleResourceDownloadSuccess" the file is DOWNLOADED PERFECTLY. (Stream.size is correct)

There are no problems in downloading, only in load / drawing inside the image.

@Zeus64
Copy link
Collaborator

Zeus64 commented Jan 9, 2025

yes, but with this code, did it work ? :

class procedure TALImage.HandleResourceDownloadSuccess(const AResponse: IHTTPResponse; var AContentStream: TMemoryStream; var AExtData: TObject);
begin
  var LResourceDownloadExtData := TALImage.TResourceDownloadExtData(AExtData);
  if LResourceDownloadExtData.owner = nil then exit;
  
  //LResourceDownloadExtData.ResourceStream := AContentStream;
  LResourceDownloadExtData.ResourceStream := TResourceStream.Create(HInstance, 'landscape', RT_RCDATA);
  
  TALGraphicThreadPool.Instance.ExecuteProc(
    CreateBufDrawable, // const AProc: TALWorkerThreadProc;
    LResourceDownloadExtData, // const AExtData: Tobject; TALGraphicThreadPool.Instance will own and release the ExtData object
    GetResourceDownloadPriority); // const APriority: Int64 = 0;
  AContentStream := nil; // AContentStream Will be free by AExtData
  AExtData := nil; // AExtData will be free by TALGraphicThreadPool.Instance
end;

I start to think that your OpenGL version in your s24 android phone is not working with background context / shared context.

@Zeus64
Copy link
Collaborator

Zeus64 commented Jan 9, 2025

I’m now certain that the problem lies in the OpenGL context sharing on your phone, which isn’t working as expected. The bad news is that the Samsung S24 is quite an expensive phone, so it will be difficult for me to test it anytime soon.

I’m fairly confident that if you do the following:

class procedure TALImage.HandleResourceDownloadSuccess(const AResponse: IHTTPResponse; var AContentStream: TMemoryStream; var AExtData: TObject);
begin
  var LResourceDownloadExtData := TALImage.TResourceDownloadExtData(AExtData);
  if LResourceDownloadExtData.owner = nil then exit;
  LResourceDownloadExtData.ResourceStream := AContentStream; 

  TThread.synchronize(nil, 
    procedure
    begin
        CreateBufDrawable(LResourceDownloadExtData);
    end);

  AContentStream := nil; // AContentStream Will be free by AExtData
  AExtData := nil; // AExtData will be free by TALGraphicThreadPool.Instance
end;

then it's will work

@maurobotta
Copy link
Author

maurobotta commented Jan 9, 2025

Error in compiling: CreateBufDrawable is not a Class Visible

[DCC Error] Alcinoe.FMX.Objects.pas(1750): E2250 There is no overloaded version of 'CreateBufDrawable' that can be called with these arguments

@Zeus64
Copy link
Collaborator

Zeus64 commented Jan 9, 2025

so try instead this :

class procedure TALImage.HandleResourceDownloadSuccess(const AResponse: IHTTPResponse; var AContentStream: TMemoryStream; var AExtData: TObject);
begin
  var LResourceDownloadExtData := TALImage.TResourceDownloadExtData(AExtData);
  if LResourceDownloadExtData.owner = nil then exit;
  LResourceDownloadExtData.ResourceStream := AContentStream;

  TThread.synchronize(nil,
    procedure
    begin
      var tmp: Tobject := LResourceDownloadExtData;
      TALImage.CreateBufDrawable(tmp);
    end);

  AContentStream := nil; // AContentStream Will be free by AExtData
  AExtData := nil; // AExtData will be free by TALGraphicThreadPool.Instance
end;

@maurobotta
Copy link
Author

maurobotta commented Jan 10, 2025

@Zeus64

YES WORK FINE NOW !! on Samsung S24 Phone ,too :)

TThread.synchronize(nil,
procedure
begin
var tmp: Tobject := LResourceDownloadExtData;
TALImage.CreateBufDrawable(tmp);
end);

@Zeus64
Copy link
Collaborator

Zeus64 commented Jan 10, 2025

No, it's not working fine. :( This test simply shows that on your phone, you can't create a texture in a background thread, which is not normal. We need to check whether this issue is specific to the S24 phone (possibly due to a bad OpenGL implementation) or if it's a broader problem. What is certain is that I need to be able to reproduce the issue, but on all the phones I have, I can't. :( I'll need to investigate further, but in the meantime, you can try using the SKIA canvas instead of the OpenGL canvas. I suspect that with the SKIA canvas, it will work in a background thread.

@Zeus64
Copy link
Collaborator

Zeus64 commented Jan 11, 2025

I managed to find an S24 device and was able to reproduce the problem. I’ve already found a fix: it seems that on the S24, when creating a texture in a background thread, we must call glFinish before using it on the main thread. Could you update your Alcinoe repository to the latest commit and try again?

@maurobotta
Copy link
Author

Hi @Zeus64

I have download now last update and work fine on my Samsung S24 Ultra.

i have tested on:

Windows 32: OK

Samsung Tablet 2024 TAB A9+ : OK

Samsung S24 Ultra : OK

iPhone 11 PRO Max : OK

@maurobotta
Copy link
Author

May add HTTP support to TALRectangle ?

@Zeus64
Copy link
Collaborator

Zeus64 commented Jan 14, 2025

Perfect! :)
Currently, HTTP support only works with TALImage. Regarding images, TALImage and TALRectangle are very similar; they are essentially the same component and use the same functions. However, TALImage offers additional functionality for working with images (e.g., blur, HTTP support, etc.). What do you want to achieve with TALRectangle that you can't do with TALImage?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants