[vlc-devel] [PATCH 00/13] Execute medialib queries out of the UI thread

Romain Vimont rom1v at videolabs.io
Mon Nov 23 17:30:14 CET 2020


Currently, the Qt interface for medialibrary executes database queries from the
UI thread. As a consequence, every I/O blocking results in a freeze of the
whole VLC interface. In practice, on my computer, during medialibrary
indexation, it is common that VLC is frozen for tens of seconds (e.g. 45
seconds) on scrolling or click on a tab.

There are two major (and independent) issues:
 1. I/O on the UI thread (#22687)
 2. database lock starvation while indexing

This patchsets aims to fix the first one.

Even if the average query duration might sometimes be acceptable (at least with
an SSD), there may be I/O delay peaks making the UI laggy. Such I/O latency
should never freeze the whole application. Therefore, VLC should never execute
I/O (in particular database queries) from the UI thread. The problem is made
obvious when the database lock is held for tens of seconds for other queries.

The main difficulty in solving this problem lies in being able to destroy the
list model (on the UI thread) which initiated the database queries without
blocking (i.e. without waiting for the requests to finish), leaking or
undefined behavior.


## Patchset description

After some minor cleanups/preparation (patches 1 to 4), the real first step
consists in extracting a list cache, independant of the list model, in order to
avoid mixing independent concerns (patches 5 to 7). The cache strategy is left
unchanged (1 local page of 100 items aligned on multiples of 100) for now.

Next, data loaders are separated from the list model instances (patch 8).
This paves the way to destroy the list models without waiting for any pending
requests (which would block the UI thread).

Then, medialib queries are executed from a separate thread pool (patches 9 to
12), tied to the medialib instance (so it can outlive list models, but not the
medialib, required for executing queries). An AsyncTask API (patch 10) helps
executing a task on a thread pool and retrieve the result on the main thread,
and properly handle the case where the receiver is destroyed while a processing
is still running.

Finally, patch 13 declares QML images asynchronous to avoid more small freezes
on thumbnail/cover display.


## Remaining work

After these changes, the UI is not frozen by database queries anymore. However,
some database queries may still be very long, due to database lock starvation
while indexing. I will investigate this separate problem later.

There is still some work related to asynchronous loading:
 - the UI should show that some background tasks are running (to let the user
   know that the visible data is not up-to-date)
 - a "cache miss" item should be designed (currently, it shows "unknown name"
   with a cone)
 - the cache strategy is suboptimal (if items of consecutive cache pages are
   visible simultaneously, the cache will invalidate its data on each refresh);
 - there are still "small" freezes sometimes (~250ms), but not always, when
   updating the UI list once the database query result is available; it
   requires more investigations
 - the list model abstract class (MLSlidingWindowModel) is templated, causing
   big compilation times on every change (which probably does not work the cost,
   since the concrete classes use QVariant to expose the data to Qt anyway)


Branch: https://code.videolan.org/rom1v/vlc/commits/asyncml.v1

Regards

Romain Vimont (13):
  qt: medialib: make fetch() const
  qt: medialib: remove unused get()
  qt: medialib: do not count on item()
  qt: medialib: pass explicit query parameters
  qt: medialib: introduce list cache
  qt: medialib: use list cache from MLBaseModel
  qt: medialib: pass loader via a raw pointer
  qt: medialib: implement separate data loaders
  qt: medialib: define a medialib thread pool
  qt: medialib: introduce async task
  qt: medialib: make cache load() asynchronous
  qt: medialib: make cache count() asynchronous
  qt: load QML images asynchronously

 modules/gui/qt/Makefile.am                    |   6 +
 modules/gui/qt/medialibrary/medialib.cpp      |   3 +
 modules/gui/qt/medialibrary/medialib.hpp      |   4 +
 modules/gui/qt/medialibrary/mlalbummodel.cpp  |  48 ++-
 modules/gui/qt/medialibrary/mlalbummodel.hpp  |  12 +-
 .../gui/qt/medialibrary/mlalbumtrackmodel.cpp |  62 ++--
 .../gui/qt/medialibrary/mlalbumtrackmodel.hpp |  12 +-
 modules/gui/qt/medialibrary/mlartistmodel.cpp |  61 ++--
 modules/gui/qt/medialibrary/mlartistmodel.hpp |  12 +-
 modules/gui/qt/medialibrary/mlbasemodel.cpp   |  54 ++-
 modules/gui/qt/medialibrary/mlbasemodel.hpp   | 160 +++++----
 modules/gui/qt/medialibrary/mlgenremodel.cpp  |  53 +--
 modules/gui/qt/medialibrary/mlgenremodel.hpp  |  12 +-
 modules/gui/qt/medialibrary/mlqueryparams.cpp |  14 +
 modules/gui/qt/medialibrary/mlqueryparams.hpp |  68 ++++
 .../gui/qt/medialibrary/mlrecentsmodel.cpp    |  74 ++--
 .../gui/qt/medialibrary/mlrecentsmodel.hpp    |  20 +-
 .../qt/medialibrary/mlrecentsvideomodel.cpp   |  70 ++--
 .../qt/medialibrary/mlrecentsvideomodel.hpp   |  24 +-
 modules/gui/qt/medialibrary/mlurlmodel.cpp    |  53 +--
 modules/gui/qt/medialibrary/mlurlmodel.hpp    |  12 +-
 modules/gui/qt/medialibrary/mlvideomodel.cpp  |  50 +--
 modules/gui/qt/medialibrary/mlvideomodel.hpp  |  12 +-
 .../qt/medialibrary/qml/ArtistTopBanner.qml   |   1 +
 .../qml/MusicAlbumsGridExpandDelegate.qml     |   1 +
 .../medialibrary/qml/VideoInfoExpandPanel.qml |   1 +
 modules/gui/qt/util/asynctask.hpp             | 250 +++++++++++++
 modules/gui/qt/util/listcache.hpp             | 337 ++++++++++++++++++
 modules/gui/qt/widgets/qml/RoundImage.qml     |   1 +
 29 files changed, 1200 insertions(+), 287 deletions(-)
 create mode 100644 modules/gui/qt/medialibrary/mlqueryparams.cpp
 create mode 100644 modules/gui/qt/medialibrary/mlqueryparams.hpp
 create mode 100644 modules/gui/qt/util/asynctask.hpp
 create mode 100644 modules/gui/qt/util/listcache.hpp

-- 
2.29.2



More information about the vlc-devel mailing list