-
-
Notifications
You must be signed in to change notification settings - Fork 584
XWIKI-22540: Slow loading time when changing the icons theme to Silk in the Icon picker #3537
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
base: master
Are you sure you want to change the base?
Conversation
…in the Icon picker * Added a flag on the data_icons action to only retrieve metadata when necessary. This shaves off half of the time for the request and reduces significantly the size of the payload
…in the Icon picker * Refactored the IconPicker javascript to improve readability
…in the Icon picker * Removed unwanted changes
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Adding a flag for the metadata is a good idea, but I think the real fix is to add pagination to the icon picker. Loading more icons could be triggered by scroll or by clicking on a "Load more..." link. Also, the icon filtering could be done server side (I already added support for this on d80394a).
@@ -52,6 +52,7 @@ define('xwiki-iconService', [ | |||
iconsPromise = iconsPromisesPerTheme[query] = $.getJSON(getResourceURL('data_icons', { | |||
iconTheme, | |||
query, | |||
'metadata': 'true' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
'metadata': 'true' | |
metadata: true |
I'm wondering if this can't be considered a breaking change by those (extensions) that use the icon picker data_icons
URL as an API. Sure, it's not as public / advertised as the icon REST API, but wouldn't it be safer to return the icon metadata by default (i.e. keep the current behavior) and to pass metadata: false
when you don't need it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Those metadatas were added in 15.7, with https://jira.xwiki.org/browse/XWIKI-20979.
It's likely that most uses of this API in the extensions/user customizations do not need or want those metadatas and got significantly slower when we added them by default. IMO the default should still be without it: in our use cases it has been reported as a performance regression, and I think it would end up similarly for most customizations.
At the end of the day, we need to choose one:
- Break extensions made between 15.7 and 16.10 that rely on the metadata.
- Have all extensions relying on this rest API being twice as slow as they were before 15.7
Note that if we chose the first one, we can add a note about it in the release notes, and with the appropriate documentation update, it should be quite straightforward to fix for the impacted extension maintainers.
I'm keeping the PR as is for now, let me know if you think my argumentation and choice is not correct and I'll update it :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK, let's keep it like this then, and add a note in the RN.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should cache the icon metadata, and make it fast through the cache, not by excluding the metadata by default.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For me the priority should be to add some kind of pagination to the icon picker because it doesn't scale currently. Adding the icon metadata cache is nice, but I'm not sure if it will solve the slowness (for an image-based icon theme like Silk where the icon picker needs to fetch and display 1k+ image icons).
.../xwiki-platform-icon/xwiki-platform-icon-ui/src/main/resources/IconThemesCode/IconPicker.xml
Outdated
Show resolved
Hide resolved
.../xwiki-platform-icon/xwiki-platform-icon-ui/src/main/resources/IconThemesCode/IconPicker.xml
Outdated
Show resolved
Hide resolved
.../xwiki-platform-icon/xwiki-platform-icon-ui/src/main/resources/IconThemesCode/IconPicker.xml
Outdated
Show resolved
Hide resolved
…in the Icon picker * Fix codestyle Co-authored-by: Marius Dumitru Florea <marius@xwiki.com>
…in the Icon picker * Fixed codestyle I didn't rerun all the tests. Co-authored-by: Marius Dumitru Florea <marius@xwiki.com>
.../xwiki-platform-icon/xwiki-platform-icon-ui/src/main/resources/IconThemesCode/IconPicker.xml
Outdated
Show resolved
Hide resolved
…in the Icon picker * (WIP) * Check for the state of loaded icons and load new icons when the scroll reaches the bottom (see line 309) * Implement an additional cache?
.../xwiki-platform-icon/xwiki-platform-icon-ui/src/main/resources/IconThemesCode/IconPicker.xml
Outdated
Show resolved
Hide resolved
.../xwiki-platform-icon/xwiki-platform-icon-ui/src/main/resources/IconThemesCode/IconPicker.xml
Outdated
Show resolved
Hide resolved
.../xwiki-platform-icon/xwiki-platform-icon-ui/src/main/resources/IconThemesCode/IconPicker.xml
Outdated
Show resolved
Hide resolved
.../xwiki-platform-icon/xwiki-platform-icon-ui/src/main/resources/IconThemesCode/IconPicker.xml
Outdated
Show resolved
Hide resolved
.../xwiki-platform-icon/xwiki-platform-icon-ui/src/main/resources/IconThemesCode/IconPicker.xml
Outdated
Show resolved
Hide resolved
…in the Icon picker * Implemented a part by part load. * No cache. * Improved various code quality related to comments from this morning.
…in the Icon picker * Improved code style
…in the Icon picker * Improved request action name formatting.
…in the Icon picker * Improved request action name formatting.
…in the Icon picker * Improved performance of `limit` icon requests.
…in the Icon picker * Escaped special characters
…in the Icon picker * Improved code style
Here is the current state of things after 8a7c415 : 2025-01-13.16-21-50.mp4We can see here that there is no more of a slowness issue. The icons are loaded 20 by 20 and the user can start using the picker before they are all loaded. When looking at the issue, I figured that the actual use of pagination was quite reduced since most users are already used to searching icons with the input filter. Instead of making everything more complex by adding full blown pagination, I decided to just keep a I didn't change the metadata handling compared to before, and I didn't implement a cache. There's already some kind of cache in javascript so we'd need to concile both caches. Note that on the demo above, my machine's resources were under a lot of stress while recording (and I didn't reboot in a while...), so it was still quite slow. It's nowhere near as annoying as it became and the first render should have a similar speed than what used to be (request to get iconCount + getting 20 icons vs request to get 140 icons). |
Getting back on this: |
…in the Icon picker * Fixed the spinner not disappearing when changing the icontheme before the initial one is fully loaded.
In my manual tests, I tried to make sure that even on low network, interacting with the component while it's in an unstable state wouldn't break it. E.g. changing iconTheme while the iconTheme is not yet fully loaded. |
#if ("$!iconNamePrefix" == '' || $stringtool.startsWithIgnoreCase($xwikiIcon, $iconNamePrefix)) | ||
## We compare $foreach.count - 1 to our values since foreach.count is 1 based index (!= standard 0 based index) | ||
## We want to make sure we retrieve only the right values. | ||
#if (($foreach.count - 1 >= $offset) && (!$limit || $foreach.count - 1 < $offset + $limit)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
#if (($foreach.count - 1 >= $offset) && (!$limit || $foreach.count - 1 < $offset + $limit)) | |
#if ($foreach.index >= $offset && (!$limit || $foreach.index < $offset + $limit)) |
$foreach.index
is also available, and it's 0-based, see https://github.com/search?q=repo%3Axwiki%2Fxwiki-platform+%22foreach.index%22+language%3AXML&type=code&l=XML .
var pageSize = 20; | ||
var maxItems = -1; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
var pageSize = 20; | |
var maxItems = -1; | |
const pageSize = 20; | |
let maxItems = -1; |
var maxItems = -1; | ||
// Recursive function helper. This calls the page to retrieve the icon information, by chunk of pageSize. | ||
// After receiving the icon info, it displays them and calls itself again if the colortheme is not fully loaded. | ||
var partialLoadIcon = function () { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
var partialLoadIcon = function () { | |
function partialLoadIcon() { |
// After receiving the icon info, it displays them and calls itself again if the colortheme is not fully loaded. | ||
var partialLoadIcon = function () { | ||
let itemCount = icons[iconTheme].length; | ||
if( maxItems === -1) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if( maxItems === -1) { | |
if (maxItems === -1) { |
} | ||
// Whatever the value of the current icon theme, we finish loading this one so that we have a correct state | ||
// if the user ever comes back to it. | ||
if (itemCount + pageSize < maxItems) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's no guarantee that maxItems
was updated by the first request when this code is called. You have two HTTP requests sent one after another, but there's no guarantee that the response will come in the order the requests were made. It will happen most of the time, but when it doesn't the icon theme will remain partially loaded. I think you should wait for the icon count to be retrieved before starting to fetch the icons (e.g. make partialLoadIcon
async and use await
), or you could also always include the total count in the response that returns the icons.
#set ($icon = { | ||
'name': $xwikiIcon, | ||
'render': $services.icon.renderHTML($xwikiIcon, $iconTheme) | ||
'render': $services.icon.renderHTML($xwikiIcon, $iconTheme), | ||
'queryString': $iconNamePrefix |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Where is this used client-side?
Jira URL
https://jira.xwiki.org/browse/XWIKI-22540
Changes
Description
Clarifications
Screenshots & Video
N/A, performance issue only
Executed Tests
Manual tests, time to display was reduced by half. Locally, the request before the changes would take about 5 seconds. This was most of the waiting time. After the PR, this request was only half as long (2 to 2.5s).
Expected merging strategy