Architecture for UI and database interaction
#1
I would like to discuss some architectural fundamentals regading the databases (no matter how they are implemented) and UI interaction, and how we intend to achieve them

@FernetMenta has said “DB operations on the main and renderthread are a major design flaw. OnSomething() methods are not supposed to by hijacked by heavy call like db queries.

I understand that the general aim is to remove any expensive function calls from both the main and render threads, so that the player and UI can continue smoothly and not be blocked by other activity. But what activities are most expensive and need to be addressed first? And how are we planning to do this?

The comment from Fernet came up in the context of the Song Info dialog, and that a change I had implemented (inline with how other dialogs are done) had somehow missed an opportunity to remove a flaw. But it is not at all clear to me how that could have been achieved (just for that one dialog in time for RC), or even that the music info dialogs do currently present any kind of blocking or heavy processing. It is important to note that the music info dialogs are more than just "popups", they also provide navigation around the music library, and as such I believe it is correct that they fetch the data needed for display as the user navigates through it.

It got me thinking about the UI and db interaction more generally. As I see it there are parts of the UI whose very purpose is to sit on top the db. They display data retrieved from the db, takes input for data to be saved in the db, and provide navigation to other dialogs that display other data retrieved from the db. When using the UI to browse data it is those places that attempt to load all the data from the db into a CFileItem structure that are slow e.g. songs node. The db query is fast, what we then do with the results set is the “heavy processing”. Far better is a design that fetches just the data it needs just in time for display, and keeps movement from results set to some other structures to a minimum.

Some other thread could do the db read/write, but the UI thread would have to wait for it to have something to display I really don’t see the point in that particular separation, what will that gain? Generally db queries are not slow or heavy, it is the crazy way Kodi juggles and manipulates the data it has fetched that needs redesign.

My background is database dependant applications (24/7 mission critical systems), I see things from that view point. There are aspects of Kodi that is just that: it turns a collection of music or video files into an enhanced library that can be explored in a variety of ways and empowers users to browse their collection and select what they want to play. Of course it is much more, and maybe that area needs isolating in some way.

Or maybe I see this all wrong? Either way I would like to discuss how we intend to achieve whatever we want to achieve, so that I and others can collaborate and contribute effectively.
Reply
#2
I'm not into core that much but I just want to mention that you can't expect a query you fire to be "fast".
It probably is when you have your local sqlite database, but what if you use a remote database with bad connection?
(I've seen people who connect to a db via vpn hosted at their homes. Who know how fast that's going to be)
Reply
#3
Remote connections could be slow, a valid point. Thanks @tadly.

As I see it that situation gives 2 design options: a) the UI has to wait for the data no matter if it is on a separate thread; b) all data is gathered locally first just in case the UI wants to show it. With b) the question is how do you store it locally in a way that has all the flexible accessiblity and speed of an RDBMS. A spaggetti of linked lists and pointers, or a relational database? I would pick the db.

It seems with our current implementation, despite lots of the time having a local db, we still have moments like the songs node where we take approach b) fetch all the data and stuff it into a spaggetti of CFileItem just to show a small subset of it. Those few occassions where we look up an album or an artist from the db from a dialog are trivial by comparison.

I would guess what we want is for any shuffling between local storage and remote storeage to be fully encapsulated and hidden from the UI. But the UI still need to get the data from this thing as it needs it and may have to wait even when locally held.
Reply
#4
Just to make sure I understood the problem. You/We want to display data without blocking the main and/or render thread right?

Isn't that what you'd use lazy loading for?
At least the requests would be kept to a minimum that way.
Whether a main/render thread does the request (hence everything blocks) or you inject new items into the current view (from a totally different thread) is another story (I think).

Sorry if I completely missed the point Huh
Reply
#5
It might also happen, that a addon/multiple addons all call to a table your accessing and end up blocking/deadlocking you. It's unlikely, but it can happen in theory.
Reply
#6
I'm a strong believer in fetching just the data needed just in time to display it, and where we don't do that now things are slow. Using lazy loading is one desireable tool, and would help with the songs node for instance, but not with the user picking their way though item details say from a song to an artist to artist details to an album to...

Can you expand on the value of a UI, that's purpose is to show data, being able to render empty before the data arrives if there has been an unavoidable delay in getting that data? That is the point I am slow to grasp. Allow cancellation of that display I guess. As it is the skins show an "hourglass" cursor of somekind if CFileItem processing is being slow, it is not blank but there is no way to back out until you are in. Is that the reason for having a separate thread? Is that the gain?

So getting the data to display is to happen in a separate thread, how is that best done? Is there some aspect of Kodi that already does something like it that could be duplicated? How is the UI going to know the data has arrived now an can be rendered too (the boilerplate of the UI possibly already having been rendered without data values)? Polling? Or is going to wait, and risk being blocked anyway?
Reply
#7
As I said before, I'm not a core dev nor do I know how any of that stuff works right now.

In terms of "What to display if there isn't anything to display yet".
Usually you show and empty view with an "infinite loading animation" and maybe even show some text telling the user that data is currently being
fetched (just so it looks less empty).
Android Example

A user could than back out if he decides that this wasn't what he wanted to do (and you'd just interrupt the thread and release all resources or catch them or whatever...).

Don't pin me on that though. I didn't properly read up on those design pattern.
I'm just brainstorming here ;)

Btw.
IIRC lazy loading has been discussed a few times since I'm a member and I bet it has been discussed many more times before that.
I'm pretty sure this isn't trivial to implement otherwise this would have probably happened already (one way or another)
Reply
#8
I still need to understand why a UI, that's purpose is to display data, wants to do something other than wait for the data it is going to display to arrive before rendering?
Reply
#9
The main point is that when you do the query in the UI thread you have no way to provide the user with a possibility to cancel it because that would also have to happen in the UI thread but that thread is already being blocked by your database query. Therefore querying should happen in a different thread which will free the UI thread to show a progress dialog with the possibility to cancel the operation. Obviously you have to wait for the data to become available.

We already do this in several places e.g. when cleaning the database or when installing an addon.

Another important point is that the UI should not really have to know where the data is coming from. It should not have to know that it comes from the DB. So that will require some abstraction as well.
Always read the online manual (wiki), FAQ (wiki) and search the forum before posting.
Do not e-mail Team Kodi members directly asking for support. Read/follow the forum rules (wiki).
Please read the pages on troubleshooting (wiki) and bug reporting (wiki) before reporting issues.
Reply
#10
Just so I understand correctly.
When you say "...wants to do something other than wait for the data..." does this mean the UI would freeze/lock for the amount of time it would process the data it wants to display?

If so, what would happen if kodi has to display a notification while you wait for your the data to display (I'm sure there are more and better examples)?
If not, no idea where the problem is as it's already async at that point Big Grin
Reply
#11
Right now the UI will freeze/lock before opening the info dialog because it starts loading additional data from the database. On normal setups you won't really notice the freeze/lock because it's just a split second but on slow connections you would certainly notice it. That's why it needs to happen asynchronously so that we can still show feedback to the user and also show other stuff like notifications which are happening as well.
Always read the online manual (wiki), FAQ (wiki) and search the forum before posting.
Do not e-mail Team Kodi members directly asking for support. Read/follow the forum rules (wiki).
Please read the pages on troubleshooting (wiki) and bug reporting (wiki) before reporting issues.
Reply
#12
Thanks for input @Montellese.

Sure data access for the UI needs to be encapsulated, moreover I would like to see the whole FileItem spaggetti reworked.

I can understand why cleaning the database or installing an addon are done asynchronously, there is no need for the user to wait for those. But for all UI data fetching to be asynchronous so that a progress dialog with the possibility to cancel the operation can be shown any time a delay occurs seems extreme (or at very least cumbersome), especially since you seem to suggest that the UI would still wait to render anyway. Or did I misunderstand?

If the data to UI isn't being responsive then we need to sort that out. If Kodi is intended to run down a wet piece of string then maybe some part of it needs to have a local database sync mode in the same way that Kore works.

Part of what confuses me is that for say the slow songs node now, all on same thread, I see a whirling cursor and I can back out from it using Esc or Back Tab. The UI does not appear to freeze, or is that an illusion?
Reply
#13
My personal meaning for this is: If rendering is a critical task, it should NOT be handled in main thread.
For me main thread is for UI and should be allowed to deadlock if required.

I would be to lazy to to tell people that they should not use mainthread for specific tasks. Better place critical tasks ito an own thread.

I have a bluetooth keyboard, wich disconnects after 20 secs idle. If I reactivate the keyboard, I always have small interupts of running media (bacause render pipeline is blocked).

I have only small overview about why something's concept is as it is. But I was a little bit surprised at the time I learned that rendering is mainthread.
So sorry if I missed something...
Reply
#14
(2016-11-28, 19:35)peak3d Wrote: For me main thread is for UI and should be allowed to deadlock if required.

Not sure yet but i think you might have made my day here Big Grin
AppleTV4/iPhone/iPod/iPad: HowTo find debug logs and everything else which the devs like so much: click here
HowTo setup NFS for Kodi: NFS (wiki)
HowTo configure avahi (zeroconf): Avahi_Zeroconf (wiki)
READ THE IOS FAQ!: iOS FAQ (wiki)
Reply
#15
(2016-11-28, 19:35)peak3d Wrote: For me main thread is for UI and should be allowed to deadlock if required.

Not sure yet but i think you might have made my day here Big Grin
AppleTV4/iPhone/iPod/iPad: HowTo find debug logs and everything else which the devs like so much: click here
HowTo setup NFS for Kodi: NFS (wiki)
HowTo configure avahi (zeroconf): Avahi_Zeroconf (wiki)
READ THE IOS FAQ!: iOS FAQ (wiki)
Reply

Logout Mark Read Team Forum Stats Members Help
Architecture for UI and database interaction0