Difegue / LANraragi

Web application for archival and reading of manga/doujinshi. Lightweight and Docker-ready for NAS/servers.

Home Page:https://lrr.tvc-16.science

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Respect preload setting when resizing in reader enabled

anonstash opened this issue · comments

Currently it seems that images are not preloaded and/or pre-resized when resize in reader is enabled. Advancing the page results in a noticeable lag every time. It would be a significantly better user experience if the same number of "preload" images were resized ahead of time (assuming they require resizing) to reduce this reading lag. Another small thing to note is that it seems resized images are not kept in the cache after exiting the reader and returning, but it would be better to just leave them there.

After reading the code, I see why resized images aren't loaded from cache, as there is currently no logic in Model::serve_page to check whether or not the resized image already exists before serving:

# This API can only serve files from the temp folder
    if ( index( $abspath, $tempfldr ) != -1 ) {

        # Apply resizing transformation if set in Settings
        if ( LANraragi::Model::Config->enable_resize ) {

            # Store resized files in a subfolder of the ID's temp folder
            my $resized_file = "$tempfldr/$id/resized/$path";
            my ( $n, $resized_folder, $e ) = fileparse( $resized_file, qr/\.[^.]*/ );
            make_path($resized_folder);

            $logger->debug("Copying file to $resized_folder for resize transformation");
            cp( $file, $resized_file ); # At this point the existing file is overwritten

However, I can't seem to understand why there is a lag when advancing the page as I don't see any logic which would prevent preloading pages when resize in reader is enabled. I'm currently under the impression that in reader.js the src used by loadImage() results in a call to Model::serve_page, is that not the case?

Thanks for noticing! I've added some logic to try serving existing resized files if they're present.

As for the preload issues, you're correct that the src attribute is what triggers serve_page; I know we don't precache the HEAD request we do to get size/etc, but I don't think that should cause any issues with resized versions.. I'll try to dig a bit more.

Thanks for that fix! Tested it on the nightly and resized images are being sent from the cache now.
I tried to do some more digging as to why there's a lag when advancing the page and here's what I've noticed:

  • The correct number of resized images show up in the server's temp folder ahead of time (based on the preload setting)
  • There's a lag in the client when advancing the page only when the page has never been viewed before by any client (browser). If the page has already been viewed by some client, any subsequent view by another client will not experience the lag.
  • If jumping directly to a page which has already been resized but never viewed before, there is no lag. Additionally, going backwards from this page does not cause any lag.

Hopefully this can help narrow it down a bit. If I get time I can also help take a look at the code.

EDIT: I used in-browser developer tools to confirm that your hunch about the HEAD request seems to be right. When the lag happens, there's a pending request for the next preload page as well as a pending XHR request for the page being advanced to. While the client is lagging, you can scroll down and see that although the image itself has already updated, the file info hasn't. Once the XHR request completes, the file info updates and the page becomes responsive again.

It's also worth mentioning that when the page being preloaded doesn't need to be resized by the server (already resized before), the lag doesn't happen. My guess is either one of two things is happening:

  1. The server gets bogged down with the resizing and so isn't able to respond to other requests in a timely fashion due to CPU contention.
  2. The resizing completely blocks the other request thread somehow (I haven't bothered checking for a counterexample where the XHR request completes before a resize).
    I haven't investigated the server threading model either so not sure which one it is.

I'll leave it up to you to decide how to approach this as I'm guessing there are a couple possibilities:

  • If scenario 2 is actually happening, then fixing that could make this problem go away
  • Pre-caching the HEAD request like you mentioned
  • Client doesn't block while waiting for HEAD request response
  • Somehow partition web-server resources from resize resources