pigallery2 icon indicating copy to clipboard operation
pigallery2 copied to clipboard

[Suggestion] Use masonry layout (paging load) and lazy load of images

Open bebestmaple opened this issue 2 years ago • 19 comments

hi,

The index load very slowly because too many images (totally 10k+ folder and 300k+ images), I am very confused why not to use the masonry layout ( or paging load) and lazy loading of images.

bebestmaple avatar Mar 02 '22 13:03 bebestmaple

I prefer the current layout and the app does lazy loading on the images.

bpatrik avatar Mar 02 '22 17:03 bpatrik

But if the data is too large, the 'gallery' page would render quite slowly and may cause the browser to crash . Also the images dose not lazy loading on the 'gallery' page, cause I can see the image request even if I dont scoll the page.

bebestmaple avatar Mar 03 '22 15:03 bebestmaple

I also like the current layout, just suggest adding paging loading to this layout.

bebestmaple avatar Mar 03 '22 15:03 bebestmaple

I believe this will also improve performance. #437

bebestmaple avatar Mar 03 '22 15:03 bebestmaple

Unless if you list the whole gallery (be e.g.: searching for something like .) this should not be an issue. Given that you did not switch of lazy loading: kép

The extra image request you see in the network tab of the dev console comes from that app loads a few extra line of images, so when you scroll they are ready to show. It should not be more than a 5-20 photos (each a few KB).

The current issue with https://github.com/bpatrik/pigallery2/issues/437 is that on a big directory (containing 3000+ photos in a single directory) or too general search that return too many photos, downloading the metadata of the photos takes too long.

In https://github.com/bpatrik/pigallery2/issues/437 downloading the metadata of 60k photos takes 33MB.

Changing the layout or the rendering of the photos wont help with the metadata. Doing streaming or any partial load would be an option but that would make local sorting and filters impossible therefore I'm not exploring these options at the moment. Also this is a directory first gallery. I do not think having several thousand photos in one directory is a general use-case (like in your case 300/10 = 30 photos/directory on average). This is an other reason why investing in streaming metadata loading does not worth it.

The slow first loading comes from the underlying angular technology which I'm not considering changing.

bpatrik avatar Mar 03 '22 22:03 bpatrik

Im sure i have switched on the 'Lazy image rendering' setting. plz see the screenshot below: image

But it still loaded all images, not lazy load, when i request the 'gallery' page, plz see the screenshot below :

image

This page shows far fewer than 398 images, and it would continue to send image request until all images on this page are loaded.

bebestmaple avatar Mar 04 '22 08:03 bebestmaple

that looks odd. I could not reproduce the issue.

What version of the app are you using? Is this a chrome browser? What is you operating system? Do you see it when you just open one of your directory and do not do any scrolling?

bpatrik avatar Mar 04 '22 16:03 bpatrik

[UPDATE]: never mind. this is not the issue.

~having a second though this might be the side effect of the on-demand thumbnail generation.~ ~If that is really the case here you can avoid it in 2 ways:~

  • ~let it run once. next time it wont do it~
  • ~pregenerate all thumbnails in the settings [advanced mode] -> jobs~

~although I did not look closely, not sure if this is the real problem~

bpatrik avatar Mar 04 '22 17:03 bpatrik

Server : PiGallery:nightly-alpine docker images on Unraid OS Client : Chrome 98.0.4758.102 (64-bit) on Windows 10

YES! I also see it when I open on subdirectory and do not any scrolling.

bebestmaple avatar Mar 05 '22 04:03 bebestmaple

strange. I don't think the server side env. plays a role here and I tested in the same client side environment.

This is where I test if more photos should be loaded:

https://github.com/bpatrik/pigallery2/blob/8f6f960ee8db4011c0e22c6e83e39079f94c7eac/src/frontend/app/ui/duplicates/duplicates.component.ts#L134-L138

Related variables: https://github.com/bpatrik/pigallery2/blob/5ad9a65a01092c11fa020d99a2ed23d23d0e1c8d/src/frontend/app/model/page.helper.ts#L10-L12

https://github.com/bpatrik/pigallery2/blob/5ad9a65a01092c11fa020d99a2ed23d23d0e1c8d/src/frontend/app/model/page.helper.ts#L18-L22


Do you happen to have some aggressive add blocker / ani-tracing add-on that prevents accessing scroll-bar position?

bpatrik avatar Mar 05 '22 11:03 bpatrik

NO.I have tired to disable all add-in and clear the browser cache, nothing changed. Im trying to debug now, it would call the 'ThumbnailLoaderService' ( /src/frontend/app/ui/gallery/thumbnailLoader.service.ts line 23 ), the que.Length is 2K+. too large?

bebestmaple avatar Mar 05 '22 14:03 bebestmaple

Yeah that is expected that ThumbnailLoaderService has a huge queue. That loads the photos.

What does the code above show if you execute them in the dev console? I mean runnig something like this: this.supportPageOffset ? window.pageYOffset : this.isCSS1Compat ? document.documentElement.scrollTop : document.body.scrollTop Or each of them separately and Math.max(document.body.scrollHeight, document.body.offsetHeight, document.documentElement.clientHeight, document.documentElement.scrollHeight, document.documentElement.offsetHeight) - window.innerHeight;

bpatrik avatar Mar 05 '22 22:03 bpatrik

image

Strangely, I set a breakpoint in the shouldRenderMore() method and it didn't hit, the breakpoint in renderPhotos() did.

I am not very familiar with frontend, and don't know the relationship between the task in ThumbnailLoaderService and shouldRenderMore() method,but what I see is a huge queue in the ThumbnailLoaderService to create the Image and set the Image's src. It would send image request when set the image's src?

@Injectable()
export class ThumbnailLoaderService {

  que: Array<ThumbnailTask> = [];
  runningRequests = 0;

  constructor(private galleryCacheService: GalleryCacheService) {
  }

  run = (): void => {
    if (this.que.length === 0 || this.runningRequests >= Config.Client.Media.Thumbnail.concurrentThumbnailGenerations) {
      return;
    }
    const task = this.getNextTask();

    if (task === null) {
      return;
    }

    this.runningRequests++;
    task.taskEntities.forEach((te): void => te.listener.onStartedLoading());
    task.inProgress = true;

    const curImg = new Image();
    curImg.onload = (): void => {
      task.onLoaded();
      task.taskEntities.forEach((te: ThumbnailTaskEntity): void => te.listener.onLoad());

      this.taskReady(task);
      this.runningRequests--;
      this.run();
    };

    curImg.onerror = (error): void => {
      task.taskEntities.forEach((te: ThumbnailTaskEntity): void => te.listener.onError(error));

      this.taskReady(task);
      this.runningRequests--;
      this.run();
    };

    curImg.src = task.path;
  };

bebestmaple avatar Mar 06 '22 02:03 bebestmaple

I cannot reproduce this either on my huge photo database, perhaps I/O bottleneck (hard-drive)?

desertwitch avatar Mar 06 '22 10:03 desertwitch

I/O bottleneck? It should not be, because although there are 2K+ image requests when I subsequently reopen the page , but they are using browser cache(disk cache or memory cache), I now suspect the ThumbnailLoaderService. What is the role of the ThumbnailLoaderService, plz? is it create 2k+ image requests?

bebestmaple avatar Mar 08 '22 03:03 bebestmaple

A point that needs to be reiterated is: my gallery page is all directory, so all image requests are thumbnail of the directory.

bebestmaple avatar Mar 08 '22 03:03 bebestmaple

I did not have time to look into it yet. I suspect the issue is on client side and with the grid component.

ThumbnailLoaderService is a helper service that grid component and any other component that renders photos are using to queue up photos that do not have available thumbnails (server inject that information in advance) for thumbnail generation. (This is a mechanism that tries to protect the server from flooding it with thumbnail generation requests which take "long time").

In comment https://github.com/bpatrik/pigallery2/issues/447#issuecomment-1059748443, I referenced the wrong component. This should be the function that decides if the grid should load more photos: https://github.com/bpatrik/pigallery2/blob/11ed54669a06d1a657accdc45b11debb3b39750d/src/frontend/app/ui/gallery/grid/grid.gallery.component.ts#L263-L274

bpatrik avatar Mar 08 '22 08:03 bpatrik

Ok, looking forward to fixing this bug, I'm not good at frontend and can't figure out exactly where the bug is and fix it. It looks like ThumbnailLoaderService should also use shouldRenderMore(offset) to determine if thumbnail generation requests should be push into the queue, but I wasn't able to find out if there was a place where it was using shouldRenderMore(offset) to determine that, and I suspect more than anything that it wasn't using this method to determine that, otherwise there shouldn't be so many thumbnail generation requests. But I will continue to try to debug

bebestmaple avatar Mar 09 '22 03:03 bebestmaple

I had a look, but unfortunately I could not find anything.

This is the place where more photos added to the render queue (thus to the ThumbnailLoaderService): https://github.com/bpatrik/pigallery2/blob/c1cd10a9d142f90c1b26e040bd8297ff58f78e74/src/frontend/app/ui/gallery/grid/grid.gallery.component.ts#L173

It is in the renderARow function that is called from this function:

https://github.com/bpatrik/pigallery2/blob/c1cd10a9d142f90c1b26e040bd8297ff58f78e74/src/frontend/app/ui/gallery/grid/grid.gallery.component.ts#L276-L283

As you can see renderPhotos function is guarded by the shouldRenderMore function.

bpatrik avatar Mar 10 '22 19:03 bpatrik

Closing this due to inactivity. Feel free to reopen if you think otherwise.

bpatrik avatar Dec 18 '22 21:12 bpatrik