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

Improve performance of webui and sort table #2469

Merged
merged 8 commits into from
Apr 18, 2023

Conversation

TrimmingFool
Copy link
Contributor

@TrimmingFool TrimmingFool commented Mar 30, 2023

On each list update, addTorrents caused ruTorrent to become unresponsive for a short period of time. This is very noticeable when thousands of torrents are refreshed. Primarily, this was due to calling format in setValue regardless of whether the value has changed.

There are multiple performance improvements in this PR:

  • Sort table
    • Calls to setValue, add/remove/hide/unhideRow, clearRows, resize or scrollTo will not update the DOM immediately. Instead, changes are written to pendingSync and after delaying with a debounce of 50ms or a throttle of 500ms the DOM is updated.
    • setValue now considers the table cell value as dirty if the val changed instead of fmtVal. It appears, that checking the formatted value was only done to update Last Updated column in the Trackers table.
    • refreshRows now adds extra rows to the DOM in order to avoid blank (padding) regions becoming visible when scrolling.
  • WebUI
    • addTorrents now uses a background task which is implemented with requestIdleCallback. Except for the first load, the task will only run during the allotted time. Due to setLazy(true) and the debounce of 50ms the sort table will only be updated once addTorrents is done. Further, updateLabels and other DOM updates are done after the task is done in an requestAnimationFrame callback.
    • updateLabel now avoids DOM updates if its data has not changed.
    • matchTegs now uses pre-initialized regular expression objects.
    • updatePeers now caches its values similar to updateTrackers.

@stickz https://github.com/Novik/ruTorrent/releases/tag/v4.1-beta.1 My pleasure! At the moment I have no further changes in store.

Resolved issue: changes to to rowdata were immediately applied to the DOM.
This results in a busy event loop which can cause the framerate to jitter.

Avoid update in `setValue` if `val` has not changed
and modify `last` in `trk` table as `val` instead of format value

Move DOM updates out of synchronous table methods to syncDOM

Use syncDOM to update dirty rows. Sort or refresh rows as needed

Utilize new and existing sort table methods in theWebUI

Cache fetched peers by torrent hash
Resovled issue: when updating thousands of torrents
the UI gets unresponsive due to a busy event loop.

Add a background task class which uses `requestIdleCallback`

Add fallback for browsers not supporting `requestIdleCallback`

Start a BackgroundTask for addTorrents and cancel previous task.
After the task is done we update the DOM via `requestAnimationFrame`.
When scrolling, missing rows can become visible.
Adding extra rows above and below the viewing area
mitigates this artifact for moderate scrolling speeds.

Remove unused maxViewRows option.
@stickz
Copy link
Collaborator

stickz commented Mar 30, 2023

@TrimmingFool I can't merge this pull request until the next development cycle of version 4.2. There are already major changes to stable.js and webui.js in version 4.1. We won't be able to track changes and fix bugs. It could be a couple months.

I already made optimizations to ruTorrent for thousands of torrents. The situation here is not dire. These changes are drastic and need to be tested thoroughly before I can even release a beta version for them. The performance gains are small for most users.

Would you be interested in taking a look at the etags for plugin caching? They are broken and causing web browser caching issues. We can load ruTorrent in 300ms (3 times faster) for most users, if we fix this problem and re-enable the feature. This is the last element for near instantaneous loading times. I already optimized out everything else out including addTorrents.

@TrimmingFool
Copy link
Contributor Author

TrimmingFool commented Mar 31, 2023

I can't merge this pull request until the next development cycle of version 4.2

@stickz I also see no rush 👍

I already made optimizations to ruTorrent [...] including addTorrents

You optimized the first load time. However, this PR eliminates hanging during periodic GUI updates.

Would you be interested in taking a look at the etags for plugin caching?

I looked into it. We could get the etag matching $_SERVER['HTTP_IF_NONE_MATCH'] == $etag working with:

$etag = '"'.strtoupper(dechex(crc32($content))).'"';
// The ETag may gain encoding info. For instance: "{fingerprint}-gzip"
Utility::str_starts_with(trim($_SERVER['HTTP_IF_NONE_MATCH'], '"'), trim($etag, '"')))

Unfortunately, it seems that this is not fixed so easily.

At the point where Cached::send is called, most of the processing/loading is already done. I tested that returning 304 Not Modified at that point does not provide a speedup.
If we assume that users do not update the plugin sources (and expect the changes to show up without disabling the cache), we could try exiting getplugins.php early with 304 Not Modified by deriving the etag from a version number. However, loading all php plugins by calling require_once (or by simply not exiting early) should not be forgotten.

That being said, I am not interested in implementing this myself, though.

TrimmingFool and others added 3 commits April 2, 2023 21:36
Using Element.replaceChildren is faster than
individual append/remove operations.
@stickz stickz merged commit 8750ee2 into Novik:develop Apr 18, 2023
@stickz
Copy link
Collaborator

stickz commented Apr 18, 2023

@TrimmingFool Could you give the develop branch a try to confirm your changes work correctly. There were some conflicts with the last v4.1 stable release I had to resolve. https://github.com/Novik/ruTorrent/releases/tag/v4.1

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

Successfully merging this pull request may close these issues.

None yet

2 participants