cozy
cozy copied to clipboard
Books and chapter screen load times could be improved
Bug/Feature description
As per our conversation under PR #516, let's consider performance improvements to the two screens in question. If you have multiple books in your library or a book consists of a large number of chapters and/or tracks, the load times can get noticeably slow, particularly if you run Cozy on less powerful hardware. This is not great user experience (UX) as users don't get any feedback after clicking on a book so they don't know if the application has stopped responding or maybe the screen they've requested eventually shows up.
There are at least two options worth considering:
- A progress indicator that would let the user know something is happening in the background and they simply need to wait a few moments before their library or a book is ready to interact with. So this is basically a UI improvement that, in theory, should be easier to implement than option 2.
- Lazy loading the library and book screens. So e.g. with the book screen you would be expected to be redirected to it immediately after clicking a book in the library and wait until the chapter/track listing is ready. This could also be aided with a progress indicator for better UX.
Steps to reproduce
- Make sure you have a access to a machine with slow CPU and limited RAM memory
- Import a book with a large number of tracks
- Select this book on the library screen
- Notice nothing happens as the book loads in background, there's no UI indicator about the underlying task running in background. The book details screen eventually shows up but this can take a few seconds, depending on the size of the book.
- The same applies to the library screen when you have a large number of books in place.
System Information
- Operating System: any (tested on Ubuntu 20.10 and Ubuntu MATE 20.10 running on RaspberryPi 4 8GB RAM)
- Installation source: Flatpak
- Version of cozy: 0.9.5+
This is definitely an issue and related to https://github.com/geigi/cozy/issues/435 (application startup).
Here is what happens after clicking on a book in the book_detail_view
:
https://github.com/geigi/cozy/blob/5dfe78c395e25622fd34e6af33841c0af305e7cb/cozy/ui/book_detail_view.py#L98-L126
Some information about the book_detail_view:
- Most UI elements are present and only need to be filled with the correct content
- If a book is changed all chapter UI elements will be destroyed and new ones will be generated. This is probably the culprit
- Notice that first all information is set and all chapter elements are generated before the UI switches to the detail view in L125
Some general information :
- Everything after clicking on a book is happening in the main thread
- Every change in the UI must happen in the main thread but you can schedule work from other Threads in the main Thread: https://github.com/geigi/cozy/blob/4bd3a3048218ce284a4988e14f1db219eadde3ec/cozy/architecture/event_sender.py#L25
Regarding option 1: Because the main thread is 100% used after clicking on a book, a loading indicator will freeze for the time until everything is ready. We could make this possible by scheduling the work with GDK (see the more detailed version below).
Here are some ideas we could try for option 2, which should also provide the best UX:
- How does the UI behave when we switch to the book detail view before generating the chapters? This might be a bad idea because maybe the user will see the previous book data displayed for a short time.
- We could set the basic book information (title, image, ...) and switch to the book detail view. This should be quite fast. After that is completed we can trigger the chapter reload. But instead of just doing the work right away we can schedule this using
Gdk.threads_add_idle
. This scheduler is smart enough to still do UI updates even if there is work to be done so we could display a loading indicator or something else in the chapter list. The chapter loading would then no longer block the main thread as Gdk is responsible for properly scheduling it. Here is some additional information about this function: https://lazka.github.io/pgi-docs/Gdk-3.0/functions.html#Gdk.threads_add_idle
Most UI elements are present and only need to be filled with the correct content
That actually confirms my theory that I forgot to mention in the description: it is not the amount of stuff that needs to be rendered in the UI (or, at least, it doesn't seem to be the deciding factor) but the preceding operations that are slowing the whole thing. I've confirmed it by commenting out
https://github.com/geigi/cozy/blob/5dfe78c395e25622fd34e6af33841c0af305e7cb/cozy/ui/chapter_element.py#L71
... and that didn't make much difference in the speed of loading the book screen.
Maybe the instantiation of all those ChapterElements
takes a long time?
BTW if you want to get the execution time of a function you can add a small annotation at the top which is included in Cozy:
@timing
def a_funciton():
pass
This prints the execution time.