[Gammaray-interest] Getting rid of "Loading..." on client side models

Volker Krause volker.krause at kdab.com
Fri Jun 7 09:37:47 CEST 2019


On Friday, 7 June 2019 05:08:37 CEST Christian Gagneraud wrote:
> On Fri, 7 Jun 2019 at 02:24, Volker Krause <volker.krause at kdab.com> wrote:
> > On Thursday, 6 June 2019 14:15:04 CEST Christian Gagneraud wrote:
> > > On Thu, 6 Jun 2019 at 01:54, Christian Gagneraud <chgans at gmail.com> 
wrote:
> > > > When programmatically using remote models to build my graphs, i have
> > > > to deal with a very annoying "feature": the lazy loading.
> > > > 
> > > > The problem is that i need to filter out these cases as a node in a
> > > > graph is uniquely identified by its object ID, and this object ID is 0
> > > > when the item/row is in the "Loading.." state, which breaks
> > > > "everything" (I need all my data sources to be complete, fully
> > > > resolved, synchronised and ordered).
> > > > So far i'm unable to "stream" the graph data (changes). I need to
> > > > rebuild it continuously, which is rather inefficient.
> > > > 
> > > > Is there a mechanism to be notified of a loading -> loaded transition?
> > > > 
> > > > Let's dream for a moment: Wouldn't it be nice to have deferred
> > > > notification of  item/row/column/... inserted/removed/changed, instead
> > > > of asynchronous content?
> > 
> > Yes, the lazy loading is getting in the way for direct use. There's good
> > reasons why it's there though, together with the change batching you
> > noticed below as well: Performance for interactive use. We didn't have a
> > lot of these optimizations initially, and it simply wasn't able to keep
> > up. If we combine content retrieval and "structure" updates (ie. data()
> > and rowCount() calls), we'd be downloading the data for all cells in a
> > 10k row model, even if you only look at 50 at a time. Worse in tree
> > models, where rowCount() is requested for every row to determine the
> > amount of children, we don't want to trigger the download recursively
> > there.
> > 
> > The batching and delayed signal emission has similar reasons, a property
> > model on QQ2 or Qt3D elements can easily change 60 times per second,
> > enough to drown an embedded device in GammaRay model updates. Some of the
> > source models implement event more aggregation on top of that, such as
> > the event model.
> > 
> > Another thing that was added in that context was the communication
> > statistics under Help -> Diagnostics (when having
> > GAMMARAY_DEVELOPERMODE=1 set in the environment), useful to see the
> > cost/impact of remote model operations.
> Thanks for sharing all these info.
> 
> I noticed the bandwidth stats messages on stdout, but man the GUI one
> is very detailed! :)
> 
> > For your use-case this isn't helping obviously. I see two options:
> > - adding a dedicated mode to the remote model for this, disabling all
> > those
> > optimizations, and with some form of done signal.
> 
> I think the optimisation are good, it's just the out-of-order and
> synchronisation with non-model remote objects that is a problem.
> This is out of scope for me to add a new mode, this is technically
> complex and time consuming.
> 
> But after looking at the remote model and the remote model server,
> I've noticed 2 interesting features:
> - The sync barrier, which seems to be used only when clearing a remote
> model on the client side. Not sure it could be used for other purpose

You are right I think. It relies on the fact that the network communication 
guarantees in-order delivery, and the remote model code flushes it's pending 
change notifications etc before sending that out IIRC. 

It's however purely done from the server perspective, you'd need that kind of 
barrier after all data has been downloaded, ie. from the client perspective. 
So I don't think it's directly usable.

> - The RemoteModelNodeState, this one is IMHO way more interesting.

Right, that is what ultimately decides whether you see "loading...", or 
whether new data is requested when we have outdated one locally (in which case 
you see that rather than "loading...").

> If your use case is to be notified that all the datas you've requested
> are now available, then it's just a matter of tracking how many nodes
> haven't had their state cleared, which is done here[1] if i'm not
> wrong.
> A simple counter will do. Maybe node state access should be wrapped by
> a seter/getter, that would maintain the counter and emit a signal when
> this counter reach 0.

Right, you should be able to both query the loading state that way and be 
notified on changes (using the RemoteModelRole::LoadingState role). The 
(mostly theoretical) exception is the in-process mode, see below.

> Maybe we could add an extra flags parameter to ObjectBroker::model,
> that would be passed down to the RemoteServer ctor.
> Since model() returns a pointer to QAIM, maybe the communication
> mechanism could be done via a self posted custom event or dynamic
> properties.
> If the self posted event could contain both the counter and the goal,
> you could use that info to update a progress bar, and take action once
> you hit 100% synced.... :)

This would indeed be easier if we'd just get a RemoteModel instance in client 
code. The reason this isn't the case is the old in-process mode, in which case 
ObjectBroker actually gives you the source model.

Eventually I'd like to get rid of that, but there are still two tools that 
only work in in-process mode, the QtScript debugger and the QTextDocument 
bounding box overlay view (needs porting to RemoteView). Telemetry data 
suggests the QtScript debugger has become largely irrelevant by now, so maybe 
that could go eventually, to unblock this. Anyway, that's going to be a longer 
term thing, for now we have to deal with getting QAIMs from ObjectBroker I 
think.

> When i do my tests against QtCreator, it can take 3 to 4 seconds to
> just get the data needed to build the initial graph.
> 
> If i'm not wrong all signals emitted by the main event loop on the
> server side will be sent over the network in their order of emission.

Yes, the basic communication is strictly in-order, for all message types, and 
can only happen from the main thread. The remote model relies on this, even if 
it then itself adds out-of-order behavior on top.

> That's all nice theory, what's your feeling about this?

I can't promise that everything I say here about the RemoteModel is 100% 
accurate, it's a long time since I wrote this and I'm trying to avoid touching 
it again ever since ;-)

Regards,
Volker

> [1] https://github.com/KDAB/GammaRay/blob/master/client/remotemodel.cpp#L373
> > - rather than going through a model, send your entire data as a signal
> > argument or synchronized property to the client, on demand. For those
> > in-order delivery is guaranteed.
> 
> That's a tempting approach, i might use that if the above idea cannot
> work or is not feasible.
> 
> > Regards,
> > Volker
> > 
> > > B/c i don't have connect notify, my approach so far was to
> > > incrementally build the list of connected objects by using a sample
> > > timer, and scanning all (pre-filtered) objects [1].
> > > This sort of worked, but i realised that model and remote object
> > > signals are received on the client side out-of order.
> > > For example at sample time, server side,  the code update the
> > > connection list, and then emit a "sampling done" signal.
> > > On the client side, remote model changes are tracked by setting a
> > > simple "need sync" flag, and then when the "sampling done"
> > > notification is received, the sync is applied if needed.
> > > This have gave me a lot of head-ache, as it turns out that the model
> > > signals can be delayed-emitted after the "sampling done" signal.
> > > It looks to me that there's some "aggregation" process going on
> > > somewhere, i don't know if it's from GammaRay or Qt.
> > > But what i've notived, is that if i reset a model a then insert rows,
> > > and then emit the "done" signal. The server will receive, the reset
> > > signal, then the "done" signal and then the aggregated "rows inserted"
> > > signal.
> > > This whole process is done with the object lock on, as it has to be an
> > > instantaneous snapshot.
> > > 
> > > Maybe i should create a PR with my server side code, so that you can
> > > have a better picture of what i'm trying to do.
> > > 
> > > Chris.
> > > 
> > > [1] The original idea was to store sender/receiver objectid/threadid,
> > > plus number of connections, but it turns out that it is impossible to
> > > track connections this way, for example you cannot detect duplicated
> > > connections w/o resetting the connection model before-hand.
> > > 
> > > > Thanks,
> > > > Chris


-- 
Volker Krause | volker.krause at kdab.com | Director of Engineering
KDAB (Deutschland) GmbH, a KDAB Group company
Tel. +49-30-521325470
KDAB - The Qt, C++ and OpenGL Experts
-------------- next part --------------
A non-text attachment was scrubbed...
Name: smime.p7s
Type: application/pkcs7-signature
Size: 3864 bytes
Desc: not available
URL: <http://mail.kdab.com/pipermail/gammaray-interest/attachments/20190607/3de3180a/attachment-0001.p7s>


More information about the Gammaray-interest mailing list